Home
All Posts
📋

[캘린더 라이브러리] Offset 추가로 선택된 월과 현재 월과의 일치 여부 검사

Created
2024/03/05
Category
Troubleshoot
3 more properties

문제의 화면

아래와 같이 3월 안에서 3월 6일을 선택했는데, 4월 6일까지 같이 선택되는 버그가 있었다.
3/6을 선택하면 4/6도 같이 선택된다.

기존 코드

선택된 날짜를 처리하는 isSelected 함수에 문제가 있는 것 같아 살펴 보았다.
const isSelected = (date: number) => { const selectedDate = new Date(displayDate); return ( date === selectedDate.getDate() && currentDate.getMonth() === selectedDate.getMonth() && currentDate.getFullYear() === selectedDate.getFullYear() ); }; <ExtraDateComponent key={`prev-${date}`} className={isSelected(date) ? 'selected' : ''} onClick={() => handleDateSelect(currentDate.getFullYear(), currentDate.getMonth() - 1, date)} > {date} </ExtraDateComponent> <DateComponent key={`current-${date}`} className={isSelected(date) ? 'selected' : isToday(date) ? 'today' : ''} onClick={() => handleDateSelect(currentDate.getFullYear(), currentDate.getMonth(), date)} > {date} </DateComponent> <ExtraDateComponent key={`next-${date}`} className={isSelected(date) ? 'selected' : ''} onClick={() => handleDateSelect(currentDate.getFullYear(), currentDate.getMonth() + 1, date)} > {date} </ExtraDateComponent>
TypeScript
복사

문제 원인과 해결 방법

살펴보면 isSelected 함수는 현재 선택된 날짜(displayDate)와 각 날짜 컴포넌트의 날짜를 비교하고 있지만, prevMonthDaysnextMonthDays에서는 해당 월을 고려하지 않고 있다. 그래서 3월 달력에서 3일을 선택하면, 4월 3일도 함께 선택되는 문제가 발생하는 것이었다.

변경된 코드

문제를 해결하기 위해 날짜가 어떤 월에 속하는지(이전 달, 현재 달, 다음 달)를 구분할 수 있도록 아래와 같이isSelected 함수를 수정해 보았다.
const isSelected = (date, monthOffset) => { const selectedDate = new Date(displayDate); // monthOffset에 이전 달(-1), 현재 달(0), 다음 달(+1)에 대한 Offset을 추가 const adjustedMonth = currentDate.getMonth() + monthOffset; return ( date === selectedDate.getDate() && adjustedMonth === selectedDate.getMonth() && currentDate.getFullYear() === selectedDate.getFullYear() ); }; // ... // 클릭 이벤트에서는 각 날짜 컴포넌트에 맞는 monthOffset을 전달 <ExtraDateComponent key={`prev-${date}`} className={isSelected(date, -1) ? 'selected' : ''} onClick={() => handleDateSelect(currentDate.getFullYear(), currentDate.getMonth() - 1, date)} > {date} </ExtraDateComponent> <DateComponent key={`current-${date}`} className={isSelected(date, 0) ? 'selected' : isToday(date) ? 'today' : ''} onClick={() => handleDateSelect(currentDate.getFullYear(), currentDate.getMonth(), date)} > {date} </DateComponent> <ExtraDateComponent key={`next-${date}`} className={isSelected(date, 1) ? 'selected' : ''} onClick={() => handleDateSelect(currentDate.getFullYear(), currentDate.getMonth() + 1, date)} > {date} </ExtraDateComponent>
JavaScript
복사
위 코드에서 isSelected 함수는 monthOffset 이라는 인자를 사용하여 선택된 날짜의 월이 현재 달력의 월과 일치하는지 여부를 검사한다. 그리고 각 날짜 컴포넌트의 클릭 이벤트에서는 해당 날짜가 속한 월의 오프셋을 전달하여, 사용자가 선택한 날짜만이 선택된 상태로 표시되도록 한다.
또한, handleDateSelect 함수에서 날짜를 선택할 때 올바른 연, 월을 계산하여 상태를 업데이트해야 하므로 이전 달의 날짜를 선택하면 월을 감소시키고, 다음 달의 날짜를 선택하면 월을 증가시켜 해당 달에 맞는 화면을 보여준다.

수정된 화면

3/6을 선택하면 3/6만 선택된다.