jotai는 re-render를 최소화하기를 원해서 나오게 된 라이브러리고, Recoil의 아토믹 모델에 영감을 받아 나타났습니다.
아톰 의존성에 기반하여 렌더가 최적화 되고 이것은 리렌더 이슈를 해결할 수 있게 도와줍니다.
Jotai는 미니멀 API를 지향하고, TypeScript 기반입니다.
React의 useState처럼 간편한 Hook으로 사용할 수 있습니다.
모든 상태는 전역적으로 접근가능하고, 쓸모 없는 리렌더는 일어나지 않습니다.
기본 사용 방법
const countAtom = atom(0)
const countryAtom = atom('Japan')
Recoil에서는 아래와 같이 문자열 key가 존재해야하지만, jotai는 key가 따로 존재하지 않습니다.
const countAtom = atom({
key: 'countAtom',
default: 0
})
atom을 만들고 가져올 때에는 useState처럼 useAtom을 사용하면 됩니다.
const [count,setCount] = useAtom(countAtom);
jotai로 전역으로 상태를 관리 하기 위해서는 Provider로 감싸줘야 합니다.
const App = () => (
<Provider>
<Layout />
</Provider>
)
아래와 같이 다른 atom에 계산된 결과를 atom을 통해 볼 수도 있습니다.
Recoil에서는 이 기능을 Selector에서 따로 구현할 수 있습니다.
const doubledCountAtom = atom((get) => get(countAtom) * 2)
function DoubleCounter() {
const [doubledCount] = useAtom(doubledCountAtom)
return <h2>{doubledCount}</h2>
}
Recoil Selector일 경우
const doubledCountSelector = selector({
key: 'doubledCountSelector',
get: ({get}) => {
const countAtom = get(countAtom)
return countAtom * 2
},
});
atom의 3가지 형태
ReadOnly
const countAtom = atom(1)
const readOnlyAtom = atom((get) => get(countAtom) * 2)
WriteOnly
const countAtom = atom(0)
const multiplyCountAtom = atom(null, (get, set, by) => set(countAtom, get(countAtom) * by))
Read and Write
const countAtom = atom(1)
const decrementCountAtom = atom(
(get) => get(countAtom),
(get, set, _arg) => set(countAtom, get(countAtom) - 1),
)
비동기 작업
const fetchUrlAtom = atom(
async () => {
const response = await fetch(url)
return await response.json()
}
)
function Status() {
const [json] = useAtom(fetchUrlAtom)
Recoil은 위와 같은 기능을 Selector를 통해 구현합니다.
const fetchUrlSelector = selector({
key: 'fetchUrlSelector',
get: async ({get}) => {
const response = await fetch(url);
return response.json();
},
});
function Status() {
const json = useRecoilValue(fetchUrlSelector);
Jotai와 Recoil은 비동기 작업을 할 때 Suspense를 필요로 합니다.
onMount
onMount 함수는 Atom이 처음 사용될 때 실행 됩니다.
const anAtom = atom(1)
anAtom.onMount = (setAtom) => {
console.log('atom is mounted in provider')
setAtom(c => c + 1)
return () => { ... } // return은 unmount 될 때 수행할 작업 작성
}
Util
Jotai의 공식문서를 살펴보면 Core API 외에도 Util API에 대한 내용도 자세히 작성되어 있습니다.
그 중 atomWithStorage
라는 util API는 localStorage 나 sessionStorage에 해당 atom을 저장시키고 가져올 수 있습니다!
파라미터로는 key, initialValue, storage(optional)
세 가지가 있습니다.
key
와 initialValue
는 필수로 넣어줘야하며, storage
는 선택할 수 있습니다. 기본 값은 localStorage입니다.
해당 API를 활용해 다크모드를 쉽게 구현할 수 있습니다.
import { useAtom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
const darkModeAtom = atomWithStorage('darkMode', false)
const Page = () => {
const [darkMode, setDarkMode] = useAtom(darkModeAtom)
return (
<>
<h1>Welcome to {darkMode ? 'dark' : 'light'} mode!</h1>
<button onClick={() => setDarkMode(!darkMode)}>toggle theme</button>
</>
)
}
공식 문서를 바탕으로 기본적인 내용들을 작성했습니다.
요즘 Recoil에 흥미가 많았어서 Jotai에도 계속 눈길이 가는 것 같습니다.
다음 포스팅으로는 Jotai를 만든 다이시 카토상의 블로그 내용을 바탕으로 Jotai 튜토리얼 7가지를 올리도록 하겠습니다.
댓글