리액트 달력 만들기

Song-Minhyung·2022년 8월 9일
0

React

목록 보기
6/10

달력을 만들자

이전글에서 달력을 만들기 앞서 재사용이 가능한 테이블을 만들었다.
그래서 이제 테이블에 값을 넣기위해 배열만 생성하면 된다.
그러기 위해서 Date 객체를 사용 할 것이다.

날짜를 계산하자

달력을 만들기 위해 필요한건 별거 없다.
월의 시작 요일, 월의 마지막 날짜 이 두개만 있으면 모든 날짜를 게산할 수 있다.
이 둘을 계산하는 방법은 여러개가 있는데 간단하게 Date를 사용하는 방법을 쓸것이다.

const getMonthInfo = (year: number, month: number) => {
  // 월의 시작 요일 ( 0 ~ 6, 일요일 = 0)
  const startDay = new Date(year, month - 1, 1).getDay();
  // 월의 마지막 날짜
  const endDate = new Date(year, month, 0).getDate();
}

아 하나 빼먹은게 있는데 달이 바뀔 때 항상 4주인게 아니라 4주일때도 5주일때도 6주일때도 있다.
그래서 해당 달의 주가 몇주인지도 계산해야하는데
ceil((시작요일 + 마지막날짜) / 7)을 해주면 구할 수 있다.

배열 데이터를 생성하자

앞서만든 Table컴포넌트에 넣기위해선 2차원 배열로 넣어줘야한다.
그래서 calendarGenerator를 이제 바꿔보겠다.

const calendarGenerator = (year: number, month: number) => {
  const { endDate, startDay } = getMonthInfo(year, month);
  const weekNumber = Math.ceil((startDay + endDate) / 7);
  const calendar: number[][] = [];

  let nowDate = 0;
  let nowDay = 0;

  for (let i = 0; i < weekNumber; i++) {
    const nowWeek = [];
    for (let j = 0; j < 7; j++) {
      if (startDay <= nowDay && nowDate < endDate) {
        nowDate++;
        nowWeek.push(nowDate);
      } else {
        nowWeek.push(0);
      }
      nowDay++;
    }
    calendar.push(nowWeek);
  }

  return calendar;
};

위의 코드를 보면 calendar에 달력의 정보를 담아준다.
그리고 2중for문으로 넣어주는데 방법은 이렇다.

  1. 달력앞의 빈칸을 처리하기위해 startDay <= nowDay 조건문을 넣는다
    1-1. startDay > nowDay면 0을 넣어 빈칸으로 처리한다
    1-2. startDay <= nowDay 이라면 nowDate를 배열에 넣는다.
  2. nowDay에 1을 더한다.
  3. calendar에 한주에 해당하는 배열을 넣는다.

달력을 그리자

이제 모든 준비는 끝났다. 데이터를 만들어 달력을 그려주기만 하면 된다.
Table에 넣어줄 rows, titles를 아래처럼 만들어준다.

const titles = ['일', '월', '화', '수', '목', '금', '토'];
const rows = () => {
  const datas = calendarGenerator(2022, 8);
  const components: TTableData[] = [];

  // 주 반복
  datas.forEach((week, idx) => {
    const weeks: TTableColumns[] = [];

    // 일 반복
    week.forEach((date, idx) => {
      weeks.push({
        // 빈칸일때는 key가 중복되므로 idx를 넣어줌
        key: date ? date : idx,
        // 빈칸일때는 아무것도 안나오고 값이 있다면 날짜를 넣어줌
        render: date ? <span>{date}</span> : <span />,
      });
    });

    // 해당 주의 컴포넌트들
    const weekData: TTableData = {
      id: `w_${8}${idx}`,
      columns: weeks,
    };
    components.push(weekData);
  });

  return components;
};

그리고 Table에 이 값을 넣어준다.

<Table
  headers={titles}
  rows={rows()}
/>

그러면 아래처럼 달력이 생성된다!!

profile
기록하는 블로그

0개의 댓글