UX·UI - FrontEnd Dev. Story

프론트엔드/React

React Typescript 년/월/일 select option 날짜선택 개발하기

클로이겅쥬 2025. 6. 10. 17:13
반응형

 

 

 

작업을 하다보니 년 / 월 / 일자별로 값을 불러오도록 작성해야하는 일들이 빈번하게 있다.

이번기회에 React에서 사용할 typescript 버전으로 select 옵션에 value값이 들어가도록 작성해보자.

 

 

 

1. 년도 selectbox 만들

export const calendarYear = () => {
  const [year, setYear] = useState<string>('') //년도 
  const startYear = 1990
  const endYear = new Date().getFullYear() + 15 // 현재년도 + 15
  const years: number[] = Array.from({ length: +endYear - startYear + 1 }, (_, i) => startYear + i)

  const handleYearChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setYear(e.target.value)
  }
   return (
    <select name="year" value={year} onChange={handleYearChange}>
        <option value="년도">년도</option>
        {years.map((y) => (
          <option key={y} value={y}>
            {y}
          </option>
        ))}
      </select>
   )
}

 

 

 

 

 

2. 월별 selectbox 만들기

export const calendarMonth = () => {
  const [month, setMonth] = useState<string>('') // 월
  const months: number[] = Array.from({ length: 12 }, (_, i) => i + 1)

  const handleMonthChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setMonth(e.target.value)
  }
  
  return (
      {/* 월 */}
      <select name="month" value={month} onChange={handleMonthChange}>
        <option value="월">월</option>
        {months.map((mm) => (
          <option key={mm} value={mm}>
            {mm.toString().padStart(2, '0')}
          </option>
        ))}
      </select>
   )
}

 

 

 

 

 

3. 일자별 selectbox 만들기

일자는 년도와 월 별로 일의 토탈 개수가 달라지기 때문에 이를 계산 할 수 있도록 코드를 작성해야한다.

년도와 월에 따라 컨트롤 되기 때문에 위에 작성한 컴포넌트와 함께 사용해보자.

 

export const calendarDays = () => {
  const [year, setYear] = useState<string>('') //년도
  const [month, setMonth] = useState<string>('') // 월
  const [day, setDay] = useState<string>('') // 일
  const [daysInMonth, setDaysInMonth] = useState<number[]>([]) // 월별 일자 구분
  const [taskText, setTaskText] = useState<string>('') // 월별 일자 구분

  const startYear = 1990
  const endYear = new Date().getFullYear() + 15
  const years: number[] = Array.from({ length: +endYear - startYear + 1 }, (_, i) => startYear + i)
  const months: number[] = Array.from({ length: 12 }, (_, i) => i + 1)
  // 년도 값 넣기
  const handleYearChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setYear(e.target.value)
  }
  // 월별 값 넣기
  const handleMonthChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setMonth(e.target.value)
  }
  // 년도 월별에 따라 일자 넣기
  const handleDayChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setDay(e.target.value)
  }
  
  //월과 년도에 따라 일(day)의 개수가 달라지기 때문에, 
  // 이를 자동으로 계산해 업데이트 계산 해야함
  useEffect(() => {
    if (year && month) {
      const y = parseInt(year)   // 년도
      const m = parseInt(month)  // 월
      const isLeapYear = y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)
      let lastDay = 31  // 일자 토탈 마지막 숫자
      if ([4, 6, 9, 11].includes(m)) {	// 30일달 월
        lastDay = 30
      } else if (m === 2) {		// 윤달 계산
        lastDay = isLeapYear ? 29 : 28
      }

      const days = Array.from({ length: lastDay }, (_, i) => i + 1)
      setDaysInMonth(days)
      console.log('daysInMonth', daysInMonth)

      // 현재 선택된 일이 최대일 초과 시 초기화
      if (parseInt(day) > lastDay) {
        setDay('')
      }
    } else {
      setDaysInMonth([])
      setDay('')
    }
  }, [year, month, day])

   return (
      // 년도
      <select name="year" value={year} onChange={handleYearChange}>
        <option value="년도">년도</option>
        {years.map((y) => (
          <option key={y} value={y}>
            {y}
          </option>
        ))}
      </select>
      
      // 월
      <select name="month" value={month} onChange={handleMonthChange}>
        <option value="월">월</option>
        {months.map((mm) => (
          <option key={mm} value={mm}>
            {mm.toString().padStart(2, '0')}
          </option>
        ))}
      </select>
      
      // 일자
      <select name="day" value={day} onChange={handleDayChange}>
        <option value="일">일</option>
        {daysInMonth.map((d) => (
          <option key={d} value={d}>
            {d.toString().padStart(2, '0')}
          </option>
        ))}
      </select>
   )
}
반응형