앱개발/React Native

[React Native] 옆으로 스크롤링 하는 달력 만들기

Heeyeon Choi 2025. 2. 18. 16:16
728x90

1. 결과물

 

2. Date 코드 ( moment 사용)

// components/Date.tsx
import React from 'react';
import {  Text, TouchableOpacity,View } from 'react-native';
import moment, { Moment } from 'moment';
import styles from '../styles/Calendar.style';

import 'moment/locale/ko'; // 한글 로케일을 불러옵니다.
import { theme } from '../styles/theme';
moment.locale('ko'); // 전역 locale을 한글로 설정

interface DateProps {
  date: Moment;
  onSelectDate: (date: string) => void;
  selected: string | null;
}

const DateComponent: React.FC<DateProps> = ({ date, onSelectDate, selected }) => {
  // 날짜를 'YYYY-MM-DD' 포맷으로 변환하여 비교합니다.
  const formattedDate = date.format('YYYY-MM-DD');
  const dayLabel =
    formattedDate === moment().format('YYYY-MM-DD')
      ? '오늘'
      : date.format('ddd'); // 오늘이면 '오늘', 아니면 요일 (예: Mon, Tue)
  const dayNumber = date.format('D'); // 일(day) 숫자
// 일요일이면 date.day()가 0입니다.
const isSunday = date.day() === 0;
  return (
    <TouchableOpacity
      onPress={() => onSelectDate(formattedDate)}
      style={[
        styles.card,
      ]}
    >
      <Text style={[styles.big,isSunday && { color: theme.colors.red }]}>
        {dayLabel}
      </Text>

      <View style={[styles.circle, selected === formattedDate && styles.clickedCircle]}>
        <Text
          style={[
            styles.medium,isSunday && { color: theme.colors.red },
            selected === formattedDate && styles.clickedDate,
          ]}
        >
          {dayNumber}
        </Text>
      </View>

    </TouchableOpacity>
  );
};

export default DateComponent;

- moment.locale('ko'); 을 통해 월, 화, 수, 목 , 금, 토, 일 한글로 표시

- 현재날짜오늘 이라고 표시

 

3. Calendar 코드 (Date.tsx 사용하여 달력 제작)

import React, { useState, useEffect, useCallback } from 'react';
import {
  Text,
  View,
  ScrollView,
  NativeSyntheticEvent,
  NativeScrollEvent,
} from 'react-native';
import moment, { Moment } from 'moment';
import DateComponent from './Date';
import styles from '../styles/Calendar.style';

interface CalendarProps {
  onSelectDate: (date: string) => void;
  selected: string | null;
}

const Calendar: React.FC<CalendarProps> = ({ onSelectDate, selected }) => {
  const [dates, setDates] = useState<Moment[]>([]);
  const [scrollPosition, setScrollPosition] = useState<number>(0);
  const [currentMonth, setCurrentMonth] = useState<string>('');

  // 오늘부터 14일 간의 날짜 생성
  const getDates = (): void => {
    const _dates: Moment[] = [];
    for (let i = 0; i < 14; i++) {
      const date = moment().add(i, 'days');
      _dates.push(date);
    }
    setDates(_dates);
  };

  useEffect(() => {
    getDates();
  }, []);

  const getCurrentMonth = useCallback((): void => {
    if (dates.length === 0) {return;}
    const daysOffset = scrollPosition / 80; // 80픽셀마다 하루로 계산
    const month = moment(dates[0])
      .add(daysOffset, 'days')
      .format('YYYY년 M월'); // 년도와 월을 함께 포맷팅
    setCurrentMonth(month);
  }, [dates, scrollPosition]);

  useEffect(() => {
    getCurrentMonth();
  }, [getCurrentMonth]);

  return (
    <View>
      <View>
        <Text style={styles.title}>{currentMonth}</Text>
      </View>

      <View style={styles.dateSection}>
        <View style={styles.scroll}>
          <ScrollView
            horizontal
            showsHorizontalScrollIndicator={false}
            scrollEventThrottle={16}
            onScroll={(e: NativeSyntheticEvent<NativeScrollEvent>) =>
              setScrollPosition(e.nativeEvent.contentOffset.x)
            }
          >
            {dates.map((date, index) => (
              <DateComponent
                key={index.toString()}
                date={date}
                onSelectDate={onSelectDate}
                selected={selected}
              />
            ))}
          </ScrollView>
        </View>
      </View>
    </View>
  );
};

export default Calendar;

- 오늘부터 14일 간의 날짜 생성 (코드 수정을 통해 변경 가능)

728x90