리액트 앱에 달력(react-calendar) 적용하기

khy__·2022년 2월 9일
50

React

목록 보기
9/23
post-thumbnail

본 게시글에서는 react-calendar 라이브러리로 react 앱에 달력을 적용하는 방법을 공유하고자 합니다.

React-calendar 라이브러리

React-calendar 라이브러리에 대한 설명입니다:


설치 / 기본 적용 방법

1. yarn 으로 react-calendar를 설치해주세요.

yarn add react-calendar

2. 모듈을 import 하고, css를 적용해주세요. useState를 이용해 클릭한 날짜를 표시 할 수 있습니다.

import React, { useState } from 'react';
import Calendar from 'react-calendar';
import 'react-calendar/dist/Calendar.css'; // css import

function MyApp() {
  const [value, onChange] = useState(new Date());

  return (
    <div>
      <Calendar onChange={onChange} value={value} />
    </div>
  );
}

3. 현재 클릭한 날짜를 화면에 표시할 수도 있습니다.

return (
    <div>
      <Calendar onChange={onChange} value={value} />
         <div className="text-gray-500 mt-4">
           {moment(value).format("YYYY년 MM월 DD일")} 
         </div>
    </div>
  );


심화 기능 적용


post를 작성한 날짜에 dot 표시를 추가해보겠습니다.

1. 원하는 날짜 api로 가져오기

react-query를 이용해 post를 작성한 날짜를 array 형태로 가져오도록 했습니다. 그리고 useState를 이용해 가져온 배열을 mark 라는 변수에 저장했습니다.

  const [mark, setMark] = useState([]);

  const { data } = useQuery(
    ["logDate", month],
    async () => {
      const result = await axios.get(
        `/api/healthLogs?health_log_type=DIET`
      );
      return result.data;
    },
    {
      onSuccess: (data: any) => {
        setMark(data);
       // ["2022-02-02", "2022-02-02", "2022-02-10"] 형태로 가져옴
      },
    }
  );

2. mark 배열에 해당 날짜가 존재한다면, <div class="dot"></div> html 를 추가하도록 적용했습니다.

<Calendar
  onChange={onChange}
  formatDay={(locale, date) => moment(date).format("DD")}
  value={value}
  className="mx-auto w-full text-sm border-b"
  tileContent={({ date, view }) => {
    if (mark.find((x) => x === moment(date).format("YYYY-MM-DD"))) {
      return (
       <>
         <div className="flex justify-center items-center absoluteDiv">
           <div className="dot"></div>
         </div>
       </>
     );
    }
  }}
/>

개발자 도구로 확인해보면 아래와 같이 div가 추가됩니다.

<button class="react-calendar__tile">
    <abbr>날짜</abbr>
    <!--tileContent로 추가되는 위치 시작-->
    <div class="flex ...">
        <div class="dot"></div>
    </div>
    <!--tileContent로 추가되는 위치 끝-->
</button>

3. dot class에 css 추가

.dot {
  height: 8px;
  width: 8px;
  background-color: #f87171;
  border-radius: 50%;
  display: flex;
  margin-left: 1px;
}

.dot 클래스가 추가된 화면 예시 입니다.

4. (참고) Calendar 컴포넌트의 전체 코드는 아래와 같습니다.

<Calendar
  onChange={onChange} // useState로 포커스 변경 시 현재 날짜 받아오기
  formatDay={(locale, date) => moment(date).format("DD")} // 날'일' 제외하고 숫자만 보이도록 설정
  value={value}
  minDetail="month" // 상단 네비게이션에서 '월' 단위만 보이게 설정
  maxDetail="month" // 상단 네비게이션에서 '월' 단위만 보이게 설정
  navigationLabel={null}
  showNeighboringMonth={false} //  이전, 이후 달의 날짜는 보이지 않도록 설정
  className="mx-auto w-full text-sm border-b"
  tileContent={({ date, view }) => { // 날짜 타일에 컨텐츠 추가하기 (html 태그)
    // 추가할 html 태그를 변수 초기화
    let html = [];
    // 현재 날짜가 post 작성한 날짜 배열(mark)에 있다면, dot div 추가
    if (mark.find((x) => x === moment(date).format("YYYY-MM-DD"))) {
      html.push(<div className="dot"></div>);
    }
    // 다른 조건을 주어서 html.push 에 추가적인 html 태그를 적용할 수 있음.
    return (
      <>
        <div className="flex justify-center items-center absoluteDiv">
          {html}
        </div>
      </>
    );
  }}
/>

참고

4개의 댓글

comment-user-thumbnail
2023년 9월 12일

안녕하세요 포스팅 잘 봤습니다 감사합니다. 선택된 날짜(24일)에 동그라미는 css를 어떻게 조작해야 하는지 여쭤봐도 될까요!?

3개의 답글