[React] 캘린더 컴포넌트 만들기 1

Chloé·2021년 3월 16일
2
post-custom-banner

진행 중인 프로젝트의 메인 화면에 들어갈 캘린더 컴포넌트 만들기

  • 기본적으로 사용자 호키도키님의 포스팅을 참조해서 만들되, 내가 이해할 수 있는 방식으로 뜯어냈다.

캘린더 헤더 만들기

이렇게 생긴 캘린더 헤더를 만든다. 기본적으로는 오늘의 날짜에 해당하는 달이 출력되고, 양 옆 버튼을 누르면 한 달씩 이동한다.

1. 레이아웃 잡기

import { LeftOutlined, RightOutlined } from '@ant-design/icons';
  • Ant Design의 icon을 빌려오기로 한다.
  • npm install --save @ant-design/icons 한 후, https://ant.design/components/icon/ 에서 원하는 아이콘을 골라 import 한다.
function Calendar() {

  return (
    <div className="calHeaderWrapper">
      <div className="calHeaderBtn calHeaderBeforeBtn">
        <LeftOutlined 
          style={{ color: "#EFBF43"}}
  		/>
      </div>
      <div className="calHeaderNow">
        오늘의 날짜가 들어갈 자리입니다.
      </div>
      <div className="calHeaderBtn calHeaderAfterBtn">
        <RightOutlined 
          style={{ color: "#EFBF43"}}
        />
      </div>
    </div>
  );
}

export default Calendar;

2. 오늘의 날짜 불러오기

import moment from "moment";
  • moment 라이브러리를 사용한다.
const [ month, setMonth ] = useState(moment())

...

<div className="calHeaderNow">
  { month.format('YYYY - MM') }
</div>
  • moment()로 현재 날짜를 불러올 수 있다.
  • .format 메소드를 사용해 원하는 형태로 넣어준다.

3. 월 이동 버튼 만들기

첫 번째 시도

접근 방법

  1. useState를 이용해 setMonth가 month를 변경할 수 있도록 한다. 초기값은 현재값인 moment()로 불러올 수 있다.
  2. setMonth는 moment에 1을 더하거나 빼며 month를 변경시킨다.
function Calendar() {

  return (
    <div className="calHeaderWrapper">
      <div className="calHeaderBtn calHeaderBeforeBtn">
        <LeftOutlined 
          style={{ color: "#EFBF43"}}
          onClick={() => { setMonth(month.add(-1, 'months')); console.info(month) }}
        />
      </div>
      <div className="calHeaderNow">
        { month.format('YYYY - MM') }
      </div>
      <div className="calHeaderBtn calHeaderAfterBtn">
        <RightOutlined 
          style={{ color: "#EFBF43"}}
          onClick={() => { setMonth(month.add(1, 'months')); console.info(month) }}
        />
      </div>
    </div>
  );
}

export default Calendar;
  • 위와 같이 버튼을 onClick시 useState를 이용하여 month를 하나씩 더하거나 빼도록 했다. 콘솔을 찍어보면 날짜가 한 달 단위로 바뀌는 것이 보이는데, 이상하게 가운데에 위치한 div에는 이 변화가 반영되지 않았다.
  • 함수로 선언한 다음 month를 변수로 넣어주기로 하고, useEffect를 써보기도 하는 등 다양한 방식으로 접근해 보았지만 해결할 수가 없었다.

최종 코드

접근 방법

  1. useState를 이용해 setMonth가 month를 변경할 수 있도록 한다. 초기값은 현재값인 moment()로 불러올 수 있다.
  2. setMonth는 moment에 1을 더하거나 빼며 month를 변경시킨다.
  3. viewMonth를 설정하고, 버튼을 클릭할 때 마다 viewMonth를 통째로 변경시켜준다.
function Calendar() { 
  
  const [ month, setMonth ] = useState(moment())
  const [ viewMonth, setViewMonth ] = useState(month.format('YYYY - MM'))
  
  return (
    <div className="calHeaderWrapper">
      <div className="calHeaderBtn calHeaderBeforeBtn">
        <LeftOutlined 
          style={{ color: "#EFBF43"}}
          onClick={() => { setMonth(month.add(-1, 'months')); setViewMonth(month.format('YYYY - MM')); console.info(month) }}
        />
      </div>
      <div className="calHeaderNow">
        { viewMonth }
      </div>
      <div className="calHeaderBtn calHeaderAfterBtn">
        <RightOutlined 
          style={{ color: "#EFBF43"}}
          onClick={() => { setMonth(month.add(1, 'months')); setViewMonth(month.format('YYYY - MM')); console.info(month) }}
        />
      </div>
    </div>
  );
}

export default Calendar;

4. 개선사항

  • viewMonth에서 month.format('YYYY - MM') 을 통째로 갈아끼우는 방식이 별로 마음에 들지 않는다.
    • 콘솔을 찍어보면 month의 데이터 자체가 변하고 있는 것은 맞는데, 이 month의 변화가 반영되지 않는 걸 보면 state 자체는 변경되지 않는건지?
    • .format() 메소드를 반복하지 않고, month 데이터만 넘겨줘서 변경하는 방법을 찾아보고 싶다.

팀원들과 함께 의논해 보았지만 뾰족한 방법을 찾을 수가 없었다. 우선은 덜 좋은 코드로 남겨두고 다음 단계로 넘어가는 것이 중요하다고 판단했다.
다만 걱정되는 부분은, 캘린더 본체를 출력할 때도 똑같이 month 값의 변경이 컴포넌트에 반영되지 않는 상황이 발생할 수도 있다는 것이다. 리액트의 작동 방식을 정확하게 이해하고 사용할 수 있도록 공부를 더 해야겠다는 생각을 한다.

profile
클로이 데일리 로그
post-custom-banner

0개의 댓글