본문 바로가기
React.js

Jotai - 리액트 상태 관리 라이브러리

by Zih0 2021. 10. 11.

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) 세 가지가 있습니다.

keyinitialValue는 필수로 넣어줘야하며, 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가지를 올리도록 하겠습니다.

 

댓글