반응형
🚨 React DatePicker의 Range 선택 문제 해결하기
React 프로젝트에서 DatePicker를 사용할 때, range 선택 시 첫 번째 날짜 선택 후 즉시 반영되지 않는 문제가 발생했다.
이는 React의 useState 비동기 업데이트 특성 때문인데
이 글에서는 이 문제를 해결하는 최적의 방법을 소개합니다.
1. 문제 상황
🔹 개발 조건
- DatePickerType="range" 또는 "single" (기본값은 "single")
- 달력은 하나만 사용하여 시작일과 종료일을 선택
- 첫 번째 선택한 날짜는 시작/종료일 구분 없음
- 두 번째 클릭한 날짜와 비교하여 범위를 자동 설정
- 두 번째 날짜가 더 작으면 → 첫 번째 날짜를 endDate, 두 번째 날짜를 startDate로 설정
- 두 번째 날짜가 더 크면 → 첫 번째 날짜를 startDate, 두 번째 날짜를 endDate로 설정
- isRangeSelected = true가 되면 창 닫기
- 기간 선택이 완료된 상태에서 새로 클릭하면 기존 설정 초기화 후 새 날짜 선택
2. 코드 예제 (문제 발생 코드)
const [startDate, setStartDate] = useState<Date | null>(null);
const [endDate, setEndDate] = useState<Date | null>(null);
if (!startDate || isRangeSelected) {
setStartDate(selectedDate); // 첫 번째 날짜 선택
} else {
// 두 번째 날짜와 첫 번째 날짜 비교
if (selected < startDate) {
setStartDate(selected); // 두 번째 날짜가 더 작으면 첫 번째 날짜로 설정
setEndDate(startDate); // 첫 번째 날짜를 종료일로 설정
} else {
setEndDate(selected); // 두 번째 날짜가 더 크면 종료일로 설정
}
}
3. 원인 분석 🔍
❌ 상태가 즉시 반영되지 않는 이유
useState는 비동기적으로 동작합니다.
즉, setState 호출 직후 상태가 바로 변경되지 않고, 다음 렌더링에서 반영됩니다.
💡 문제 발생 흐름
- 사용자가 날짜 A를 선택 → startDate가 A로 설정됨 (하지만 즉시 반영되지 않음)
- 사용자가 날짜 B를 선택 → startDate가 아직 이전 값을 가지고 있어서 비교가 올바르게 되지 않음
- setState가 비동기적으로 동작하여 UI 업데이트가 늦어짐 → 첫 번째 선택한 날짜가 화면에 즉시 표시되지 않음
4. 해결 방법 🚀
💡 변수로 날짜를 저장하고, 한 번에 useState 업데이트하기
- 날짜를 useState에 즉시 반영하는 대신, 로컬 변수를 사용하여 계산 후 한 번에 setState
- 첫 번째 선택한 날짜를 화면에 즉시 표시해야 하므로, selectDate라는 별도 상태를 활용
✅ 수정된 코드
const [selectDate, setSelectDate] = useState<Date | null>(null);
const [startDate, setStartDate] = useState<Date | null>(null);
const [endDate, setEndDate] = useState<Date | null>(null);
if (!selectDate || isRangeSelected) {
// 첫 번째 날짜 선택 (기존 설정 초기화)
resetRangeSelection();
setSelectDate(selected);
} else {
let start, end;
// 두 번째 날짜 선택 (범위 선택)
if (selected < selectDate) {
start = selected;
end = selectDate;
} else {
start = selectDate;
end = selected;
}
// 한 번에 상태 업데이트
setStartDate(start);
setEndDate(end);
// 선택 완료 후 이벤트 처리
if (onClose) onClose();
if (onChange) {
onChange({
start: dateToString(start),
end: dateToString(end),
});
}
}
5. 핵심 포인트 ✅
✅ 첫 번째 선택한 날짜를 UI에 즉시 반영
- selectDate를 별도 상태로 관리하여 즉시 화면에 반영
✅ 비동기적 setState 문제 해결
- startDate와 endDate를 한 번에 업데이트
- useState를 연속적으로 호출하는 대신, 변수(start, end)를 사용해 논리적으로 처리
✅ 새로운 날짜 선택 시 기존 범위 초기화
- isRangeSelected가 true가 되면 resetRangeSelection()을 호출하여 이전 설정을 초기화
- 새 날짜 선택 시 기존 startDate, endDate를 삭제하고 새 값으로 설정
6. 결론
✔ React의 useState 비동기 특성을 이해하는 것이 중요
✔ 변수(start, end)를 활용하여 한 번에 setState 적용
✔ 첫 번째 선택한 날짜가 즉시 화면에 반영되도록 selectDate 추가
반응형
'Dev > Nextjs' 카테고리의 다른 글
[Nextjs] 필터 UI → FastAPI 다중 필터 API 연결 가이드 (0) | 2025.04.01 |
---|---|
ControllerWrapper로 React Hook Form 최적화하기 (0) | 2025.03.08 |
[React-hook-form] controller-checkbox 반복문을 사용한 방식과 개별 작성 방식의 차이 (0) | 2024.10.10 |
[Nextjs]useMemo 를 이용하여 불필요한 리렌더링 문제 해결 (0) | 2024.10.05 |
🚨[Nextjs] TypeORM 순환참조 Error - TypeORM N+1 - Lazy Loading (0) | 2024.10.01 |