[React] 날짜 선택 input&calendar 컴포넌트 만들기(1)

이정수·2023년 9월 12일
0
post-thumbnail

이전에 편지를 보관하는 서비스인 서함 프로젝트를 진행하면서 다양한 인풋값들을 다룬적이 있었다. 그 중에는 날짜를 입력받는 필드가 있었는데 웹버젼에서는 모달창을 띄워서 입력받았고, Electron.js를 사용하여 만든 데스크톱 어플리케이션에서는 react-calendar 라이브러리를 활용하여 만들었었다.

이번 FMD 프로젝트에서도 실종된 동물을 등록 받는 레포트 페이지와 목격동물을 신고하는 Sight 페이지에서 각각 날짜를 입력받아야하는 미션이 주어졌다.이번에는 두 페이지에서 모두 사용가능하도록 재사용성을 염두해두며 컴포넌트를 만들어야겠다는 생각이 들었다.

UI는 기본적인 바 형태의 인풋 필드로 만들되,

요구사항 1.
날짜를 입력받으면
'20200928' -> '2020-09-28'
자동으로 특정패턴의 문자열이 되도록 만들어 보려고 한다.

요구사항 2.
인풋창 오른쪽의 캘린더 아이콘을 클릭할 경우 캘린더 UI가 나타나면서 날짜를 선택할 수 있도록 한다.

요구사항 3.
문자열로 2020-09-28로 입력이 되어 있다면 캘린더를 열었을 때도 해당 날짜에 마커가 위치해 있어야 한다.

우리팀의 프론트개발은 Next.js + typescript + twin.macro 으로 이루어진다.

1. React 파일 생성 후 기본 기능 구현

먼저 날짜선택 컴포넌트를 사용할 BottomSheetContent와 DateSelecter.tsx 파일이다.
date와 관련된 상태데이터는 부모인 BottomSheetContent에서 자식인 DateSelecter로 props를 통해 전달한다.

export default function DateSelector({ date, setDate }: IDateProps) {
  const handleDateChange = (e: any) => {
    const { value } = e.currentTarget
    setDate(value)
  }

  return (
    <div>
      <input
        type="text"
        defaultValue={date}
        placeholder="yyyy-mm-dd"
        onChange={handleDateChange}
      />
      <button type="button">
        <BiCalendar />
      </button>
    </div>
  )
}

2. 날짜 format 저장 & 입력값을 format에 맞추기

일단 현재 프로젝트의 기획에서는 'YYYY-MM-DD'형식으로 입력받도록 되어 있었다.
이후 'YYYY/MM/DD'로 바뀌더라도 코드를 갈아엎지 않고 format만 바꿀수 있도록,
구분자와 구분자의 위치를 반환하는 getSeperator함수를 작성한다.

const format = 'YYYY-MM-DD'
  const getSeperator = () => {
    const regex = /[^0-9a-zA-Z]+/
    const match = format.match(regex)
    if (match) {
      const symbol = match[0] // 구분자인 - 이 저장됨
      const indexes = []
      for (let i = 0; i < format.length; i++) {
        if (format[i] === symbol) {
          indexes.push(i)
        }
      }
      return { symbol, indexes }
    }
    return { symbol: undefined, indexes: [] }
  }
  const seperator = getSeperator()

정상적으로 반환된 seperator는 {symbol:'-', indexes:[4,7]}로 되어있다.

등록된 seporator객체에 따라 indexes의 위치에 구분자를 심어준다.

  const handleDateChange = (e: any) => {
   let currentDate = e.currentTarget.value
   if (seperator.symbol && seperator.indexes.length > 0) {
     if (currentDate.length === seperator.indexes[0]) {
       currentDate = currentDate + '-'
     } else if (currentDate.length === seperator.indexes[1]) {
       currentDate = currentDate + '-'
     }
   }
   setDate(currentDate)
 }
profile
keep on pushing

0개의 댓글