토이프로젝트로 채팅 웹을 구현하고 있었는데 생각치도 못한 부분에서 에러가 발생하고 있었다.
로그인, 로그아웃이 잘 되지않고 있던 거였는데, 원인이 뭔지 잘 파악이 안됐다.
useEffect(() => {
const unscribe = onAuthStateChanged(auth, (user) => {
setUserAuthState(user);
});
return () => unscribe();
}, [setUserAuthState]);
에러가 발생하고 있던 코드인데 뭐가 문제인지 갈피가 잡히지 않았다.
그래서 구글링을 해봤고, 원인을 찾았다.
recoil은 상태가 변경되면 이를 구독 컴포넌트에 알리고 추적하여 리렌더를 발생시키거나, 발생시키지않는 일련의 절차가 존재하는데 이 절차가 진행하는 도중 상태가 변이되는 것을 방지하기 위해 개체 '급속 동결' 기능을 도입했다고 한다.
아마 파이어베이스의 onAuthStateChanged 이벤트 핸들러는 리액트의 생명주기에 종속받지않는 부분이 있기에,
context를 사용하는 recoil과 불협화음이 있는 걸로 생각했다.
그래서 recoil의 상태 변경 흐름에 영향을 주는 것이 아닐까.
결론은 동결시킨 객체를 무시하고, 새로운 객체로 복사해서 전달해주는 방법이 있다.
useEffect(() => {
const unscribe = onAuthStateChanged(auth, (user) => {
const userCopy = JSON.parse(JSON.stringify(user));
setUserAuthState(userCopy);
});
return () => unscribe();
}, [setUserAuthState]);
그리고, atom또는 selector에 dangerouslyAllowMutability 옵션에 true를 주어 해결하는 방법이 있다.
export const userAuthState = atom<User | null>({
key: "userAuthState",
default: null,
effects: [persistAtom],
dangerouslyAllowMutability: true,
});
모쪼록 잘 해결해서 다행이다.