image

React Datepicker

태그
React
상세설명react에서 Datepicker 라이브러리 사용법
작성일자2023.10.21

날짜 선택하는 캘린더 라이브러리 중 react-datepicker를 자주 사용한다.

React Datepicker 공식 웹사이트

React Datepicker 설치

npm install react-datepicker --save
//or
yarn add react-datepicker

React Datepicker 사용법

기본 사용

import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"; // 달력 css

export default function Home() {
	const [startDate, setStartDate] = useState(new Date());
	return (
    <DatePicker selected={startDate} onChange={(date) => setStartDate(date)} />
  );
}

image

주로 Date Range를 많이 사용해서 이걸 토대로 커스텀 했다.

import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"; // 달력 css
import { ko } from "date-fns/locale";

export default function Home() {
	const [startDate, setStartDate] = useState(
    new Date(new Date().setDate(day - 7))  // 시작날짜를 오늘 날짜 7일전으로 설정
  );
  const [endDate, setEndDate] = useState(new Date());

	return (
    <div css={dateArea}>
       <form>
         <div className="datePickerArea">
           <DatePicker
              locale={ko}
              dateFormat="yyyy년 MM월 dd일"
              dateFormatCalendar="yyyy년 MM월"
              selected={startDate}
              onChange={(date) => setStartDate(date)}
              selectsStart
              startDate={startDate}
              endDate={endDate}
              maxDate={new Date()}
              disabledKeyboardNavigation
              popperPlacement="bottom"
              popperModifiers={{
	             //@ts-ignore
	             flip: {
	               behavior: ["bottom"],
	             },
	             preventOverflow: {
	               enabled: false,
	             },
	             hide: {
	                enabled: false,
                },
              }}
            />
            <span className="rangeSign">-</span>
            <DatePicker
              locale={ko}
              dateFormat="yyyy년 MM월 dd일"
              dateFormatCalendar="yyyy년 MM월"
              selected={endDate}
              onChange={(date) => setEndDate(date)}
              selectsEnd
              startDate={startDate}
              endDate={endDate}
              minDate={startDate}
              maxDate={new Date()}
              disabledKeyboardNavigation
              popperPlacement="bottom"
              popperModifiers={{
                //@ts-ignore
                flip: {
                  behavior: ["bottom"],
                },
                preventOverflow: {
                  enabled: false,
                },
                hide: {
                  enabled: false,
               },
             }}
           />
         </div>
         <button className="searchBtn">검색</button>
       </form>
    </div>
  );
}

Date Range에서 제공하는 기본 코드 외에 Range 형식에 추가적으로 적용

  • 한글로 변환하기 위해 import { ko } from "date-fns/locale"; 가져와서 locale={ko} 적용했다.
  • 그리고 dateFormat="yyyy년 MM월 dd일" dateFormatCalendar="yyyy년 MM월" 을 적용해서 날짜 표기를 기존 dd/MM/yyyy 에서 yyyy년 MM월 dd일 로 변경했다.
  • 시작일, 종료일 모두 오늘 날짜 이상으로 넘어가지 못하게 maxDate={new Date()} 추가했다.
  • disabledKeyboardNavigation 는 다른 월의 같은 날짜 자동 selected 되는 현상을 방지한다. 적용하지 않을 시 만약 2023.10.01 이 선택된 상태에서 9월로 달을 넘기면 09.01에 자동으로 selected 이 되어있다.
  • popperPlacement 는 캘린더가 보여지는 위치를 설정하는 속성이다. 여기서는 input창 아래 중앙에 달력인 나타났으면 해서 popperPlacement="bottom" 적용했다.
  • popperModifiers 는 팝업의 위치 및 모양을 조절합니다.
  • flip: { behavior : [ “… “ ] } 는 배열을 사용하여 어떤 방향으로 팝업을 뒤집을지 지정합니다. 여기서는 ["bottom"] 으로 설정하여, 팝업이 하단 방향으로 뒤집힙니다. 팝업이 원래 위치에서 공간이 부족할 경우 아래쪽으로 뒤집히도록 설정있다.
  • preventOverflow : {enabled: …} false로 설정되어 있으므로, 팝업이 화면을 벗어날 경우에도 강제로 화면 안에 유지시키지 않습니다. 이를 true로 설정하면 팝업이 화면 밖으로 나가지 않도록 제한된다.
  • hide : {enabled: …} false로 설정되어 있으므로, 팝업이 감춰지지 않도록 설정되어 있습니다. 이 옵션을 true로 설정하면 팝업이 감춰질 수 있다.
  • Style Custom

    emotion을 사용해서 Datepicker를 스타일 커스텀 했다.

    *커스텀하기 전에 React Datepicker는 rem으로 되어있어 html에 지정한 폰트 사이즈가 있으면 영향을 받아 사이즈가 변동되기때문에 유의해야한다

    const dateArea = css`
      height: 50px;
    
      > form {
        height: 100%;
        display: flex;
        align-items: center;
        gap: 10px;
        justify-content: space-between;
    
        .datePickerArea {
          display: flex;
          align-items: center;
          justify-content: space-between;
          width: 100%;
          height: 100%;
          border-radius: 30px;
          overflow: hidden;
          background: #ffd480;
    
          .rangeSign {
            font-size: 20px;
            margin: 0 10px;
          }
          .react-datepicker-wrapper {  // input 영역
            height: 100%;
            flex: 1;
    
            .react-datepicker__input-container { // input 영역
              height: 100%;
    
              input {
                width: 100%;
                height: 100%;
                font-size: 18px;
                border: none;
                text-align: center;
                background: #ffd480;
              }
            }
          }
    
          .react-datepicker {  // 달력 전체 
            border: none;
            background-color: #ffd480;
            overflow: hidden;
            border-radius: 8px;
            box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
    
            .react-datepicker__navigation { // 월변경 하는 화살표 
              top: 5px;
            }
    
            .react-datepicker__header, // 헤더
            .react-datepicker__month-container {  // 달력 전체 
              background: #ffd480;
            }
    
            .react-datepicker__navigation-icon::before {  // 월변경 하는 화살표 
              border-color: #000;
            }
    
            .react-datepicker__header {
              padding: 12px 0 0 0;
    
              .react-datepicker__current-month { // 달력에 표기되는 년도 월
                font-size: 12px;
              }
    
              .react-datepicker__day-names { // 요일을 감싸고 있는 div 태그
                margin-bottom: 0;
                padding-top: 12px;
              }
            }
            .react-datepicker__current-month,
            .react-datepicker__day-names > div,
            .react-datepicker__day {  // 날짜 
              color: #000;
            }
    
            .react-datepicker__day--disabled { // 선택이 안된 날짜
              color: #838383;
            }
    
            .react-datepicker__day--today { // 오늘 날짜
              color: #e21700;
            }
    
            .react-datepicker__day--selected,   
            .react-datepicker__day--in-range,
            .react-datepicker__day:hover:not(.react-datepicker__day--disabled) { //선택된 날짜
              background-color: #fa935f;
            }
    
            .react-datepicker__day--in-range:not(
                .react-datepicker__day--in-selecting-range  
              ) {                                            // 선택된 날자 변경시            
              background-color: rgba(33, 107, 165, 0.5);
            }
          }
        }
    
        .searchBtn {
          width: 150px;
          height: 100%;
          font-size: 16px;
          border-radius: 30px;
          background-color: #ffd480;
        }
      }
    `;

    주요 클래스명

  • .react-datepicker-wrapper / .react-datepicker__input-container 는 input 영역이다.
  • .react-datepicker 달력 전체 영역으로 달력 최 상단 클래스 그리고 .react-datepicker__month-container 가 header(년도와 월, 요일이 있는 영역), 날짜영역을 감싸는 클래스이다. 이 클래스 형제에 .react-datepicker__triangle, .react-datepicker__navigation 가 있다.
  • .react-datepicker__current-month : 달력에 표기되는 년도 월 클래스 명
  • .react-datepicker__day-names : 요일을 감싸고 있는 div 태그
  • .react-datepicker__day : 날짜
  • .react-datepicker__day--disabled : 선택이 안된 날짜
  • .react-datepicker__day--today : 오늘 날짜
  • .react-datepicker__day--selected : 선택된 날짜
  • .react-datepicker__day--in-range / .react-datepicker__day--in-selecting-range : 선택된 날짜이면 부여된다.
  • .react-datepicker__day--range-start / .react-datepicker__day--selecting-range-start : 선택된 날짜 범위 중 시작 날짜
  • .react-datepicker__day--range-end / .react-datepicker__day--selecting-range-end : 선택된 날짜 범위 중 마지막 날짜
  • .react-datepicker__day--range-start / .react-datepicker__day--selecting-range-start 차이점

    .react-datepicker__day--range-start 은 이미 선택된 첫 번째 날짜이다.

    .react-datepicker__day--selecting-range-start 은 새로운 날짜 선택 할 때 첫 번째 날짜가 변경될 시 이미 선택된 첫 번째 날짜 태그에서 변경될 날짜 태그로 이동하면서 변경 날짜 전까지 첫 번째 날짜 포함 날짜들의 배경 색이 변경된다.

    하위 코드를 통해 색상 변경 가능하다.

    .react-datepicker__day--in-range:not(.react-datepicker__day--in-selecting-range) {
        background-color: rgba(33, 107, 165, 0.5);
    }

    예시

    최종 결과물

    image