취미부자 개발자 로즈🌼
작성일
2024. 5. 23. 18:30
작성자
로즈♡

앞서 말하자면, 커스텀을 해야 해서 react-datepicker를 사용해야 하고, 

해당 css를 사용해야 해서 테일윈드를 사용 하는 분은 가능은 하지만 좋은 방법은 아닐 수 있다.

(나는 완료 후 작성하게 된 글이라.. 테일윈드 지원하는 걸로 교체 예정)

 

캘린더 사용이 되는 input을 공통으로 만들어야 했다.

 

기본 input에서 type을 date로 주면 이런 모양인데

영 예쁘지가 않다.

기획상 새로운 달력아이콘과 YYYY/MM/DD형식으로 보여줘야해서 

date를 커스텀 해야 하는 상황.

 

input만으로는 어려울 것 같고,

라이브러리 없이 만들기엔 시간이 부족할 듯 하여

아예 만드는 건 나중에 도전해보기로 했다. 

 

react-datepicker를 많이 쓰고 있어서 사용해보기로 했다.

npm install react-datepicker --save

요렇게 다운을 먼저 받아주고 사용하면 된다.

 

import DatePicker from 'react-datepicker';

<생략>
<DatePicker />

react-datepicker를 처음 사용하려 하면

위와 같은 모양으로 달력 아이콘이 없, 처음에 css를 주지 않으면 저 위치도 요소 선택으로 잡아서 볼 수 있었다. 

미처 캡처를 못했지만, 날짜 형태도 DD/MM/YY형태로 반대로 보여진다. 

 

참고로 우리 프로젝트에서는 tailwind를 사용하고 있다.

동작은 되지만 룰에는 맞지 않는다.

 

react-datepicker가 css형태로 되어 있어서 class명으로 변경가능한 반면

테일윈드는 클래스명을 부여하지 않고 넣어주게 되는 형태라...

클래스로 css주는 형태 사용하는 분은 그대로 사용해도 될 듯. 

 

찾아보니 Tailwind CSS Datepicker 또는 React Tailwindcss Datepicker 라는 게 있다!!

 

공통컴포넌트로 빠르게 먼저 작업 후 각자 페이지 진행 예정이라

테일윈드로 변경하는 방법은 리팩토링 시 변경해보고 결과를 올려봐야겠다. 

 

 

✨ 내가 만들 date input의 조건은 아래와 같다.

1. 날짜 형태 : YYYY/MM/DD

2. 달력 아이콘을 넣기

3. 달력아이콘을 클릭하면 input을 선택하게되어 달력이 오픈

4. 이전 날짜는 보이지 않도록 비활성화

5. 달력에서 날짜를 선택하면 해당 input에 선택한 날짜로 반영

6. 해당 컴포넌트를 사용하는 쪽으로 선택한 날짜를 보내기

 

/// DatePickerInput 컴포넌트 ///

import DatePicker from 'react-datepicker'; //datepicker 가져오기
import Image from 'next/Image';
import { useState, useRef } from 'react';

import 'react-datepicker/dist/react-datepicker.css';
import { subDays } from 'date-fns'; //요건 이전 날짜 숨길떄 선택적으로 필요. 

interface SelectDateProps {
  selectDate: Date | null; // 선택된 날짜를 받을 props
  onSelectedDateChange: (date: Date | null) => void; // 선택된 날짜 변경 시 호출될 콜백 함수
}

const DatePickerInput: React.FC<SelectDateProps> = ({
  selectDate,
  onSelectedDateChange,
}) => {
  const [selectedDate, setSelectedDate] = useState<Date | null>(new Date());

  const datePickerRef = useRef<DatePicker>(null); //달력아이콘 클릭 시 클릭해줄 위치(DatePicker)

  const handleImageClick = () => {
    if (datePickerRef.current) {
      datePickerRef.current.setFocus();
    }
  };

  return (
    <div className="relative w-[379px] h-[56px]">
      <DatePicker
        ref={datePickerRef} //달력아이콘 클릭 시 클릭 해 줄 위치
        className="text-black200 border border-black100 rounded px-[16px] py-[8px] bg-white w-[379px] h-[56px] text-[16px]"
        dateFormat="YY/MM/dd" //날짜 형식
        selected={selectDate || selectedDate}
        onChange={(date) => {
          onSelectedDateChange(date); //날짜 선택 시 상위로 데이터 전달
          setSelectedDate(date); // 날짜 선택 시 날짜를 셋팅해서 보여줌
        }}
        minDate={new Date()} //현재 날짜 이전은 모두 선택 불가
        // minDate={subDays(new Date(), 0)} 
        //위와 같은 역할을 하지만, 뒤의 숫자를 넣어 기준일 변경 가능. 
        //예를 들어 3을 넣으면 3일 전까지는 활성화 그 전은 선택 불가
      />
      <Image
        className="absolute top-4 right-3 cursor-pointer"
        alt="달력아이콘"
        src="/icons/calendar-minimalistic.svg"
        width={27.3}
        height={27.3}
        onClick={handleImageClick}
      />
    </div>
  );
};

export default DatePickerInput;

 

/// DatePickerInput을 사용하는 상위 컴포넌트 ///

'use client'; // next.js를 사용하다보니 최상위 클라이언트 컴포넌트에서는 기재 해줘야 한다.

import { useState } from 'react';
import DatePickerInput from '@/components/commons/DatePickerInput';

const Test = () => {
  const [parentSelectedDate, setParentSelectedDate] = useState<Date | null>(
    null,
  ); // 상위 컴포넌트에서 DatePickerInput에서 전달해준 값을 활용할 때 사용

  const handleSelectedDateChange = (date: Date | null) => {
    setParentSelectedDate(date); // SelectDate 컴포넌트로부터 전달받은 selectedDate 값을 설정
  };

  return (
    <div>
      <DatePickerInput
        selectDate={parentSelectedDate}
        onSelectedDateChange={handleSelectedDateChange}
      />
    </div>
  );
};

export default Test;

 

코드와 해당 조건의 주석으로 설명을 대신한다 :) 

 

 


* 만약, 커스텀 없이 기본 캘린더를 쓸 건데 크기가 너무 작다면? 

 

위 이미지와 인풋박스의 가로길이는 거의 동일한데

그에 비해 캘린더가 엄청 작은 걸 볼 수 있다.

 

이 라이브러리의 장점이 캘린더 자체 커스텀도 되지만, 그거까진 필요없었고,

기본이 비현실적으로 작은 이 상황이 이해가 안됐는데

이런 경우라면 전체 값으로 폰트사이즈가 설정되어있는지 확인할 필요가 있다.

 

우리팀은 초기 셋팅시 편의를 위해 누군가 font-size: 62.5%;를 넣어두었는데

(이렇게 할 경우 사이즈를 10px -> 1rem 으로 사용 가능해서 rem계산이 어렵지 않다. )

폰트 사이즈를 기준으로 사이즈가 조절이 되다보니 캘린더도 조절이 된 상황이었다. 

혹시 비슷한 경우 전역 설정을 확인하시길..

 

우리는 테일윈드사용에도 맞지 않기도 하고,

폰트사이즈에 따라 이런 라이브러리도 강제로 변경이 되다보니, 

전역 설정의 폰트사이즈는 걷어내기로 했다. 

 

어쩔 수 없이 전역 설정에 따라야 한다면..

방법이 없다. 라이브러리 문서를 보며 캘린더 커스텀을 하는 수 밖에..