일반적으로 useEffect Hook
을 사용하여 맨 처음 로컬스토리지에 값이 저장되어 있는 경우 그 값을 사용하고, 아니면 초기값으로 셋팅해주면 된다. 나는 현재 상태 관리 방식으로 Recoil
을 사용하고 있는데, Recoil Effects 공식문서를 보니 effects
를 사용하도록 권장하더라.
Compared to React Effects (React Effects와 비교)
Atom Effects는 대부분의 경우 리액트의 useEffect()로 대체될 수 있습니다. 그러나 atom의 집합은 리액트 컨텍스트의 외부에서 생성되며, 특히 동적으로 생성된 atom의 경우 리액트 컴포넌트 내에서 효과를 관리하기 어려울 수 있습니다. 또한 초기 atom 값을 초기화하거나 서버 사이드 렌더링(SSR)과 함께 사용될 수도 없습니다. atom effects를 사용하는 것은 effects와 atom 정의를 함께 배치하게 합니다.
따라서 공식 문서의 설명에 맞춰 localStorage에 값을 저장할 수 있도록 코드를 작성했다.
const localStorageEffect = (key:string) => ({setSelf, onSet}: any) => {
const savedValue = localStorage.getItem(key)
// setSelf : Callbacks to set or reset the value of the atom.
if (savedValue != null) {
setSelf(JSON.parse(savedValue));
}
// onSet : Subscribe to changes in the atom value.
onSet((newValue:any, _:any, isReset:any) => {
isReset
? localStorage.removeItem(key)
: localStorage.setItem(key, JSON.stringify(newValue));
});
};
위와 같이 함수를 작성해준 다음 atom을 정의해주는 부분에 effects
를 추가하면 된다.
/* 선택된 날짜 State */
// 서비스 시작 화면은 오늘날짜, 날짜 기준 수정 가능
const today = new Date();
export const selectedDateState = atom<Date>({
key: "selectedDateState",
default: today,
effects: [localStorageEffect('selected_date')]
});
effects: [localStorageEffect('selected_date')]
이 부분이 로컬스토리지에 전달된 문자열을 키 값으로 데이터를 저장하도록 한다.
useEffect()를 사용해서 해당 recoil의 set함수를 호출하기 전까지는 값을 호출해보면 제대로 값이 들어가있으나 local storage에서는 찾아볼 수 없다. 흠...
일단 set함수를 사용하여 예전 상태에 기반한 업데이트를 하면 default 값이 잘 들어가 있으니 일단은 크게 코드를 바꿀 건 없어서 좋았다.
effects를 사용한다고 useRecoilState()를 사용하는 방법이 달라지는 것은 아니다
Local storage에 데이터를 입출력할 때 사용되는 포맷은 JSON
이다.
따라서 나는 JS에서 지원하는 Date
객체를 사용해서 데이터를 넣었음에도 데이터를 빼보면 dateString
으로 실제로는 문자열 데이터가 리턴된다. 따라서 실제로 사용할 때는 new Date()
로 감싸서 Date 객체로 만들어줘야 Date 자료형으로 잘 작동한다.
JSON에서 넣고 뺄 때 자료형이 바뀌니 주의하자! (이건 Backend와 통신할 때도 똑같다.)