선요약: Recoil의 상태를 변경하는 함수 내에서 다시 다른 Recoil 상태를 변경하면 무한루프에 빠지는 등 문제 발생
const [month, setMonth] = useRecoilState(monthAtom);
const [year, setYear] = useRecoilState(yearAtom);
const monthOfDays = getLastOfMonth(month);
const onbeforeClick = () => {
setMonth((prev) => {
if (prev <= 1) {
setYear(prevYear => prevYear - 1)//년도를 바꾼다
return 12; // 년도를 변경한 후에 prev 값을 수정하지 않음
} else {
return prev - 1;
}
});
};
const onafterClick = () => {
setMonth((prev) => {
if (prev >= 12) {
setYear((prevYear) => prevYear + 1); //년도를 바꾼다
return 1; // 년도를 변경한 후에 prev 값을 수정하지 않음
} else {
return prev + 1;
}
});
};
현재 '달'을 바꾸는 버튼을 눌러 1월이나 12월이 넘어가면 '년도'가 바뀌도록 코드를 짰다. 하지만 저런 에러가 뜬다.
이유는 Recoil에서는 상태 업데이트 함수가 순수 함수여야하기 때문이다.
즉, 동일한 입력에 대해 항상 동일한 결과를 반환해야 한다
ex) function add(1, 2) //3을 반환 or function add(3, 2) //5를 반환
1. 상태 업데이트 함수가 순수 함수인지 확인:
onbeforeClick
및 onafterClick 함수
가 순수 함수인지 확인. 이 함수들은 상태를 변경하고 반환하는 부분에서 어떤 다른 상태 업데이트도 수행하지 않아야 한다.2. 상태 업데이트 함수 내에서 다른 상태 업데이트를 피하도록 수정:
const [month, setMonth] = useRecoilState(monthAtom);
const [year, setYear] = useRecoilState(yearAtom);
const [beforYear, setBeforeYear] = useState(false);
const [afterYear, setAfterYear] = useState(false);
const monthOfDays = getLastOfMonth(month);
const onBeforeYear = () => {};
const onbeforeClick = () => {
setMonth((prev) => {
if (prev <= 1) {
setBeforeYear(true); //이렇게 해결
return 12;
} else {
return prev - 1;
}
});
};
const onafterClick = () => {
setMonth((prev) => {
if (prev >= 12) {
setAfterYear(true);
return 1;
} else {
return prev + 1;
}
});
};
useEffect(() => { //useEffect로 특정 데이터 변경시 작동하도록 만듦
if (beforYear) {
setYear((prev) => prev - 1);
setBeforeYear(false);
}
if (afterYear) {
setYear((prev) => prev + 1);
setAfterYear(false);
}
}, [beforYear, afterYear, setYear, setBeforeYear, setAfterYear]);
setAfterYear:
setAfterYear(true)
는 로컬 상태를 변경하는 부수 효과다.로컬 상태를 변경하는 부수효과란 함수 실행 중에 발생하는 외부 상태의 변경을 의미