react는 useState()를 통해서 함수형 컴포넌트 내에서 상태를 선언하고, 변경할 수 있게 해준다. 하지만 그냥 react (리액트가 바닐라 취급이라니 진짜 어이가 없다.)에서는 useState()로 추적중인 상태는 해당 컴포넌트와 그 하위 컴포넌트에서만 쓸 수 있다. 그래서 등장한 것이 recoil, jo-tai, zustand 같은 라이브러리다.
원자형 상태관리 등등 여러 설명들이 있고, 이에 대해 이해한다면 물론 도움이 훨씬 되겠지만 jo-tai가 하는 일을 딱 한 문장으로 말하자면 상태를 전역적으로 관리할 수 있게 해준다. jo-tai를 통해 useAtom으로 지정한 state는 해당 컴포넌트는 물론 다른 컴포넌트 어느곳에서도 추적하고 값을 변경할 수 있는 것이다. 정글에서 우리 조는 이를 통해서 유저의 닉네임, 프로필 사진, 게임 종류, 참가 인원 수 등 다른 컴포넌트나 페이지에서 정한 값을 끌어오는데 사용했었다. 그런데...
jo-tai를 이용해 useAtom으로 관리중인 값은 브라우저를 새로고침 하면 사라지는 것이었다.
이를 해결하기 위해서 jo-tai refresh 이런 키워드들로 검색을 해봤으나 결과는 refresh token에 대한 글만 나왔었고 전혀 도움이 되지 않았다.
키워드를 계속 바꿔가면서 검색하다가 jo-tai 공식 문서의 persistence 항목이 나타났다. 이게 답이었다.
공식문서
해결책을 두괄식으로 한 문장으로 정리하자면, 'localStorage에 값을 저장해라.' 가 되겠다.
const strAtom = atom(localStorage.getItem('myKey') ?? 'foo')
이런 식을 써서 저장하고 싶은 값의 key: value를 localStorage에 저장할 수 있다. 하지만 이것도 좀 번거롭다.
Jo-tai playground Jo-tai의 전역 상태관리를 체험해볼 수 있는 playground 이다. 맨 처음에는 버튼을 많이 눌러서 카운터 숫자를 올리더라도, 새로고침을 하면 그 숫자들이 전부 날아가고 만다.
이 코드를
import { atom, useAtom } from 'jotai';
import { atomWithStorage } from 'jotai/utils'
const counter = atomWithStorage('counter', 0);
export default function Page() {
const [count, setCounter] = useAtom(counter);
const onClick = () => setCounter(prev => prev + 1);
return (
<div>
<h1>{count}</h1>
<button onClick={onClick}>Click</button>
</div>
이런 식으로 atomWithStorage
를 import 한 후,
atom으로 관리할 상태를 atomWithStorage()함수를 통해 '이름'과 초기값을 넣어준다.
그리고 나머지는 그냥 atom을 사용하는 방식 그대로 적용하면 된다.
물론 이 방식은 문제점이 없는 것은 아니다. 값을 초기화 하고 새로 시작하려면 localStorage를 비워야 한다. 번거롭긴 하지만 원할 때 지우고 원하지 않을 때 남아있는 방식이 좀 더 나은 것 같다.