| 항목 | 내용 |
|---|---|
| 발생 환경 | Detail/Edit 페이지에서 서버 데이터로 폼 초기값 설정 |
| 증상 | 데이터 fetch 완료 전 폼이 빈 값으로 렌더링됨 |
| 영향 범위 | 전자결재 수정, 인사정보 수정, 근태 요청 수정 등 모든 Edit 페이지 |
문제 코드 예시:
function EditApproval() {
const { data } = useQuery({ queryKey: ['approval', id] });
// 문제: data가 undefined일 때 폼이 빈 값으로 초기화됨
const { register, handleSubmit } = useForm({
defaultValues: data // undefined!
});
return <form>...</form>;
}
| 방안 | 장점 | 단점 |
|---|---|---|
| A. useEffect로 초기값 설정 | 간단하고 직관적, React 표준 패턴 | 추가 렌더링 1회 발생 |
| B. 부모-자식 컴포넌트 분리 | 깔끔한 데이터 흐름, useEffect 불필요 | 컴포넌트 구조 변경 필요 |
| C. React Query initialData | 캐시된 데이터 즉시 사용 가능 | 첫 로드 시 캐시 없으면 동일 문제 |
| D. Suspense + useSuspenseQuery | 로딩 상태 선언적 처리 | 에러 바운더리 필요, 복잡성 증가 |
선택: A안 (useEffect로 초기값 설정)
function EditApproval() {
const { data, isLoading } = useQuery({ queryKey: ['approval', id] });
const { register, handleSubmit, reset } = useForm({
defaultValues: {
title: '',
content: '',
}
});
// data가 로드되면 폼 값 업데이트
useEffect(() => {
if (data) {
reset({
title: data.title,
content: data.content,
});
}
}, [data, reset]);
if (isLoading) return <LoadingSpinner />;
return <form>...</form>;
}
| 관점 | 이유 |
|---|---|
| 팀 일관성 | 기존 코드베이스에서 동일 패턴 사용 중 |
| 디버깅 용이성 | 상태 변화 흐름을 명확하게 추적 가능 |
| 구현 속도 | 기존 컴포넌트 구조 변경 없이 빠른 적용 |
| 안정성 | React 공식 문서에서 권장하는 패턴 |
컴포넌트 분리 패턴으로 리팩토링하면 useEffect 없이도 가능: