Q&A 모달에서 새로운 문의를 작성하면 자동으로 목록이 업데이트되도록 만들고 싶었습니다.
처음에는useEffect의 의존성 배열에 setQnas를 넣으면 될 것 같았습니다. 새로 질문을 작성하면 setQnas가 변경되고, 다시 getMyQnas를 실행하여 새로고침이 가능할 것이라고 생각습니다.
const QnaModal = ({ onClose }: QnaModalProps) => {
const [qnas, setQnas] = useState([]);
useEffect(() => {
getMyQnas((response) => {
if (response) {
setQnas(response.list || response);
}
});
}, [setQnas]); // ❌ 이렇게 하면 새로고침이 안된다!
// ...
}
기대했던 동작:
- 문의 작성 완료 → setQnas 호출 → useEffect 재실행 → 목록 새로고침
-> 동작 안함!
setState 함수는 절대 변하지 않습니다.
const [qnas, setQnas] = useState([]);
이 함수는 컴포넌트가 생성될 때 한 번만 만들어지고, 절대 변경되지 않습니다.
React의 useState가 반환하는 setter 함수는 항상 동일한 참조를 유지합니다.
useEffect(() => {
// 어떤 작업
}, [setQnas]); // setQnas는 항상 같은 함수 → 변화 감지 안됨
의존성 배열은 "값이 변했을 때" useEffect를 재실행하는데, setQnas는 변하지 않으니 재실행되지 않는 것이죠.
그럼 의존성 배열에 setQnas가 아니라 qnas를 넣으면 되지 않을까? 라는 생각이 들었습니다.
const QnaModal = ({ onClose }: QnaModalProps) => {
const [qnas, setQnas] = useState([]);
useEffect(() => {
getMyQnas((response) => {
if (response) {
setQnas(response.list || response);
}
});
}, [qnas]); // ??
}
하지만 이렇게 할 경우
useEffect 실행
↓
getMyQnas API 호출
↓
setQnas(새로운 데이터) 호출
↓
qnas 값이 변경됨
↓
useEffect가 qnas 변화를 감지
↓
useEffect 다시 실행 (1번으로 돌아감)
이런 무한 반복이 발생할 수 있습니다.
제가 선택한 방법은 새로고침 함수 분리 + 필요 시 호출 입니다.
const QnaModal = ({ onClose }: QnaModalProps) => {
const [qnas, setQnas] = useState([]);
const [showCreateForm, setShowCreateForm] = useState(false);
// 1. 새로고침 로직을 별도 함수로 분리
const fetchQnas = () => {
getMyQnas((response) => {
if (response) {
setQnas(response.list || response);
}
});
};
// 2. 처음 마운트 시 한 번만 실행
useEffect(() => {
fetchQnas();
}, []); // 빈 배열
// 3. 모달 닫을 때 명시적으로 새로고침
const handleFormClose = () => {
setShowCreateForm(false);
fetchQnas(); // 여기서 새로고침!
};
// 4. 삭제 후에도 명시적으로 새로고침
const handleDeleteButton = (qnaId, e) => {
e.stopPropagation();
if (!window.confirm("이 문의를 삭제하시겠습니까?")) {
return;
}
deleteMyQnas({ id: qnaId }, (response) => {
if (response) {
alert("문의가 삭제되었습니다.");
fetchQnas(); // 여기서도 새로고침!
}
});
};
return (
<>
{/* ... */}
<QnaCreateModal
isOpen={showCreateForm}
onClose={handleFormClose} // 닫을 때 fetchQnas 호출
/>
</>
);
};
새로고침 함수를 정의해놓고 필요 시 호출하여 사용하면 되니, 더 명확하고 예측이 가능한 동작이 가능했습니다.
setState 함수는 변하지 않으니, useEffect를 통한 데이터 새로고침이 필요할 경우에는 명시적으로 함수를 정의해놓고 필요 시 호출하는 방식을 사용하면 됩니다!