Recoil은 기본적으로 컴포넌트 계층 구조를 뛰어넘어 애플리케이션 전역에서 메모리 내의 상태를 보유하고 있음
위와 같은 성질로 인해서 recoilPersist()
를 활용해서 sessionStorage에 상태를 보관하더라도, 메모리에도 남아있기 때문에 단순하게 sessionStorage를 clear하는 것으로 상태를 초기화 할 수 없다.
Recoil은 기본적으로 RecoilRoot
가 unmount되었다가 mount가 발생하면 상태를 초기화한다. 이 부분을 이용해서 명시적으로 Recoil의 상태를 초기화 할 수 있다. 아래 코드를 보자.
...생략
function TestApp (){
const [key, setKey] = useState(0);
// key 값 +1 증가
const resetRecoil = () => {
setKey(prev => prev + 1);
};
return (
<RecoilRoot key={key}>
...생략
</RecoilRoot>
);
}
위 코드에서 주목할 부분은 resetRecoil()
과 key={key}
부분이다.
React의 렌더링 규칙들 중 key값이 변경되면 해당 컴포넌트와 하위 요소들이 리렌더링 된다는 것을 알고 있을 것이다. 이러한 규칙을 이용해서 key를 명시적으로 조작하여 RecoilRoot
의 mount를 유발하는 것이다.
이렇게하면 RecoilRoot
는 mount되면서 새로운 RecoilRoot
를 생성하면서 상태가 초기화 되는 것이다. 하지만 위 코드만으로는 문제가 있다. 바로 해당 컴포넌트에서만 key의 변경을 할 수 있다는 것이다. 그렇다면 다른 컴포넌트에서도 key값을 변경시키는 방법은 무엇이 있을까?
다양한 방법들이 있겠지만 React의 Context를 이용해서 전역적으로 함수를 호출하여 실행하는 방법을 사용해보자.
// src/ResetRecoilContext.js
import React from 'react';
const ResetRecoilContext = React.createContext(null);
export default ResetRecoilContext;
위와 같이 createContext()
를 통해 전역에서 호출 할 수 있는 컨텍스트를 null
값으로 생성하고 export해준다. RecoilRoot
를 아래와 같이 해당 Context의 Provider로 감싸주고, resetRecoil()
를 value로 전달한다.
...생략
import ResetRecoilContext from './ResetRecoilContext';
function TestApp (){
const [key, setKey] = useState(0);
// key 값 +1 증가
const resetRecoil = () => {
setKey(prev => prev + 1);
};
return (
<ResetRecoilContext.Provider value={resetRecoil}
<RecoilRoot key={key}>
...생략
</RecoilRoot>
</ResetRecoilContext>
);
}
Context 하위에 RecoilRoot
가 위치했기 때문에 ResetRecoilContext
를 호출하여 value로 넘겨준 resetRecoil()
을 호출하면 아래와 같이 다른 컴포넌트에서도 전역적으로 RecoilRoot
의 key를 변경 할 수 있다.
// 컴포넌트에서 호출하기
import ResetRecoilContext from './ResetRecoilContext';
export const Test = () => {
...생략
const resetRecoil = useContext(ResetRecoilContext);
return <button onClick={resetRecoil}>초기화</button>;
};
위에서 설명한 방법은 Recoil의 특정 상태만을 변경하는 것이 아니라 모든 상태를 초기화하는 것이기 때문에 꼭 필요한 부분에서만 사용해야한다. 무분별한 사용은 원하지 않는 전역 상태를 재설정하기 때문에 애플리케이션 동작에 무리가 갈 수 있으며, 작업중인 정보가 쉽게 날라가는 경우들이 발생할 수 있다.