본문 바로가기

React

react-datepicker로 생년월일 값 받기

폼에서 생년월일에 대한 정보를 받아야 한다. 폼은 react-hook-form을 이용해 구현하였고 폼 중에 생년월일 입력 필드를 클릭하면 달력에서 연월일을 지정할 수 있도록 만들 것이다. 달력을 직접 구현하기에는 시간이 오래 걸릴 것 같아 react-datepicker를 사용하기로 했다.

 

React-datepicker란 ? 

커스터마이징이 가능한 달력을 구현할 수 있는 React 라이브러리이다.

자세한 설명은 공식문서에 잘 나와있다.

공식문서 :  https://reactdatepicker.com/

 

 

date-fns 설치하기

date-fns는 로케일 설정 및 날짜 포맷팅을 위해 사용되는 라이브러리이다.


react-datepicker는 기본적으로 영어로 달력의 내용을 표시해주기 때문에 이를 한글로 설정하기 위해 date-fns를 설치하였다.

공식문서 : https://date-fns.org/

 

타입스크립트를 함께 사용하였고 이전 버전에서는 @types/react-datepicker를 설치해줘야 했는데 최신 버전에서는 설치하지 않아도 된다.

react-datepicker 사용하기

import DatePicker from 'react-datepicker'
import {useState} from 'react'	
import 'react-datepicker/dist/react-datepicker.css'; //datepicker 기본 스타일파일

export default function Calendar() {
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
return (
  <DatePicker
      dateFormat='yyyy.MM.dd' // 날짜 포맷
      selected={selectedDate} //selectedDate에 저장된 날짜 값을 표시
      onChange={(date) => setSelectedDate(date)} //날짜 값 변경
    />
}

 

위와 같이 가장 기본적인 설정만 한 달력을 만들 수 있다.

 

react-datepicker  달력 커스터마이징 하기

조금 더 멋있는 달력을 만들기 위해 커스터마이징을 해보자.
가장 먼저 영어로 된 달력을 한글로 바꾸기 위해 다음과 설정한다.

import {ko} from 'date-fns/locale'

 

처음에 설치한 date-fns를 통해 한글로 바꿔주었다.

const handleDateChnage = (Date | null ) => {
	setDate(date)
    	onChange(date)
    } //변경된 date값 저장 함수
 <DatePicker
        locale={ko} //date-fns/locale 적용
        dateFormat="yyyy-MM-dd" //데이터 포맷팅 설정
        shouldCloseOnSelect //날짜를 선택하고 나면 자동으로 달력 닫기
        maxDate={new Date()} //현재 날짜를 기준으로 이후의 날짜 선택 x
        placeholderText="YYYY-MM-DD" //placeholder
        selected={date} //날짜 선택 값
	onChange={handleDateChange} //date값 변경
        renderCustomHeader={({
          date,
          changeYear,
          changeMonth,
          decreaseMonth,  
          increaseMonth,
          prevMonthButtonDisabled, //이전달 이동이 불가하면 disabled
          nextMonthButtonDisabled, //다음달 이동이 불가하면 disabled
        }  //rednderCustomHeader는 달력 상단 부분의 header 커스텀
/>

위와 같이 DatePicker에 설정을 추가해주었다.

달력에서 선택한 날짜가 onChage를 통해 date에 값이 저장되어 렌더링된다.

 

나는 사용자의 편의성을 위해서 년도와 월을 옵션을 통해 고를 수 있게 수정할 것이다.

import { useState } from 'react';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { ko } from 'date-fns/locale';
import * as S from './style';



export default function Calendar() {
  const [date, setDate] = useState<Date | null>(selectedDate);

  const handleDateChange = (date: Date | null) => {
    setDate(date);
    onChange(date);
  };

  return (
    <S.CalendarContainer>
      <DatePicker
        locale={ko}
        dateFormat="yyyy-MM-dd"
        shouldCloseOnSelect
        maxDate={new Date()}
        placeholderText="YYYY-MM-DD"
        selected={date}
        onChange={handleDateChange}
        renderCustomHeader={({
          date,
          changeYear,
          changeMonth,
          decreaseMonth,
          increaseMonth,
          prevMonthButtonDisabled,
          nextMonthButtonDisabled,
        }) => (
          <div>
          // month 감소 버튼
            <button onClick={decreaseMonth} disabled={prevMonthButtonDisabled}>
              &lt;
            </button>
            <span>
            //year값 출력
              <select
                value={date.getFullYear()}
                onChange={({ target: { value } }) =>
                  changeYear(parseInt(value))
                }
              >
              //year 설정(현재 년도로 부터 100개 1940~2024)
                {Array.from(
                  { length: new Date().getFullYear() - 1940 + 1 },
                  (_, i) => {
                    const year = 1940 + i;
                    return (
                      <option key={year} value={year}>
                        {year}년
                      </option>
                    );
                  }
                )}
              </select>
              //month값 출력
              <select
                value={date.getMonth()}
                onChange={({ target: { value } }) =>
                  changeMonth(parseInt(value))
                }
              >
              //month 설정(1~12월)
                {Array.from({ length: 12 }, (_, i) => (
                  <option key={i} value={i}>
                    {i + 1}월
                  </option>
                ))}
              </select>
            </span>
            // month 증가 버튼
            <button onClick={increaseMonth} disabled={nextMonthButtonDisabled}>
              &gt;
            </button>
          </div>
        )}
      />
    </S.CalendarContainer>
  );
}


생년월일을 받기 위해 현재 년도로 부터 100개, 즉 1940년~2024년까지 고를 수 있게 옵션 값들을 넣어주었고 1~12월까지 12개의 달의 옵션을 만들었다.
< 와 >  버튼을 통해 month의 증가와 감소를 바꿀 수 있으며 renderCustomHeader의 changeYear, changeMonth,의 두 옵션으로 화살표를 눌러서 일일이 바꿀수 있게 하는 것 뿐만 아니라 년도와 달을 클릭하여 드롭다운을 통해 직접 선택할 수 있게 만들었다.

위의 GIF는 import 'react-datepicker/dist/react-datepicker.css';  를 통해 불러온 기본 스타일이 적용되어 있는 상태이기 때문에 
CSS를 통해 디자인을 바꿔보자

 

CSS 적용하기

CSS를 적용할 때 시간이 많이 걸렸던 것 같다. datepicker 라이브러리의 클래스 이름값을 가져와서 일일이 수정해줘야 하기 때문에 
내가 선택한 방법은 개발자 도구에서 변경할 부분의 요소들을 하나씩 찍어보는 방법이였다.

 

이런식으로 className값을 하나씩 찾아보고 수정하였다.

import { styled } from 'styled-components';

export const CalendarContainer = styled.div`
  width: 122px;
  position: relative;

  .react-datepicker__header {
    border-radius: 20px 20px 0 0;
    background-color: #000000;
  }
  .react-datepicker {
    background-color: #ffffff;
    border-color: #000000;
    border-radius: 20px;
  }

  .react-datepicker__header .react-datepicker__current-month {
    color: #ffffff;
  }
  .react-datepicker__header .react-datepicker__day-name {
    color: #ffffff;
  }

  .react-datepicker__day--weekend {
    color: #ff0000;
  }
  .react-datepicker__day--disabled.react-datepicker__day--weekend {
    color: #ccc;
  }

  .react-datepicker__input-container input {
    width: 20.125rem;
    height: 2.125rem;
    border: none;
    border-bottom: 1px solid #ededed;
    padding: 0.5rem;
    font-size: 0.75rem;
    line-height: 1.125rem;
    color: #000000;

    &:focus {
      outline: none;
      border: 1px solid #000000;
    }
  }

  .react-datepicker__triangle {
    display: none;
  }

  .react-datepicker__month-dropdown-container,
  .react-datepicker__year-dropdown-container {
    select {
      background-color: #ffffff;
      border: 1px solid #ddd;
      border-radius: 8px;
      padding: 4px;
      font-size: 1rem;
      color: #333;
      cursor: pointer;
      appearance: none;
    }

    select::-ms-expand {
      display: none;
    }
  }
`;

나는 나의 취향에 맞게 위와 같이 CSS를 수정하였다.

완성

 

 

최종 완성본이며 선택한 날짜가 필드에 잘 출력되고 있다. 
react-datepickd 라이브러리의 class 이름들이 명확하기 때문에 각자 취향에 맞게 수정을 하면 될 것이다.