Jotai

Hoon·2023년 9월 16일
0

React

목록 보기
11/15
post-thumbnail

Jotai

Jotai : 일본어로 상태 를 뜻한다. Recoil 이라는 리액트팀에서 만든 상태관리 라이브러리에 영감을 받아 Zustand 를 만든 개발팀에서 만든 상태 관리 라이브러리 이다. hook 패턴을 사용하기에 복잡한 보일러플레이트 없이 사용할 수 있다.

Jotai 은 아주 작은 단위의 상태를 의미하는 atom 단위로 상태를 관리한다. ( = recoil)

먼저, ProviderApp 을 감싸준다.

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

root.render(
  <React.StrictMode>
    <Provider>
        <App />
    </Provider>
  </React.StrictMode>
);

아래는 Jotaiatom 을 선언하는 가장 기본적인 형태의 코드이다.

import { atom } from "jotai";

const nameAtom = atom<string>("");

아래의 코드는 선언한 atom 을 사용하는 코드이다.

import { useAtom, useAtomValue, useSetAtom } from "jotai";

const [name, setName] = useAtom(nameAtom);

// or

const name = useAtomValue(nameAtom);
const setName = useSetAtom(nameAtom);

또한, 아래처럼 recoilselector 와 같은 형태로도 atom 을 정의할수도있다.

  • Read-only atom (값을 가져오는 경우)
  • Write-only atom (값을 업데이트)
  • Read-Write atom (둘 다)
// Read-only atom
export const getToUpperNameAtom = atom((get) => {
    const name = get(nameAtom);
    return name.toUpperCase();
});

// Write-only atom
export const setToUpperNameAtom = atom(null, (get, set, update) => {
  	set(nameAtom, update.toUpperCase());
});
                                       
// Read-Write atom
export const toUpperNameAtom = atom(
  (get) => {
    const name = get(nameAtom);
    return name.toUpperCase();
  },
  (get, set, update: string) => {
    set(nameAtom, update.toUpperCase());
  }
);                      

만약, initialValue를 동적으로 주고싶다면 아래의 코드를 활용할 수 있다. (근데 사실 useEffect 로 set해주것과 일치)

currentSecondAtom.onMount = (set) => {
	set(new Date().getSeconds().toString());
};

Jotai Utils

atom 선언시 초기값으로의 reset 이 필요한 상황이라면, 아래와 같이 atomWithReset 으로 선언 후 useResetAtom 을 사용할 수 있다.

import { atomWithReset, useResetAtom } from "jotai/utils";

// const nameAtom = atom("");
const nameAtom = atomWithReset("");

const resetName = useResetAtom(nameAtom);

또한 atomWithStorage 를 활용해 atomlocal storagesession storage 에 저장할 수 있는 기능도 제공한다.

import { atom } from "jotai";
import { atomWithStorage } from "jotai/utils";

const darkModeAtom = atomWithStorage("darkMode", false);

const [darkMode, setDarkMode] = useAtom(darkModeAtom);

이외에도 atomWithImmer 등 여러가지 util 관련 hook이 존재한다.

async 처리

간단한 비동기 처리는 아래와 같이 처리할 수 있다.

import { atom, useAtomValue } from "jotai";

const fetchAtom = atom(async (get) => {
  const response = await fetch("https://jsonplaceholder.typicode.com/todos");
  return response.json();
});

const fetchData = useAtomValue(fetchAtom);

하지만 이러한 방식의 경우 Suspense 를 같이 사용해주어야한다.

// index.tsx

... 
  <Suspense fallback={<div>loading...</div>}>
    <App />
  </Suspense>
...

Suspense 를 쓰지않고 아래의 방식도 가능하다. (오랜만에 Jotai 사용해서 몰랐는데 v2에는 loadable utils로 아래의 방식 제공하는듯...)

// atom.ts
type ResultType = {
  loading: boolean;
  error: unknown | null;
  data: any;
};

const fetchResultAtom = atom<ResultType>({
  loading: true,
  error: null,
  data: null,
});

const fetchAtom = atom(
  (get) => get(fetchResultAtom),
  (get, set, url: string) => {
    const fetchData = async () => {
      set(fetchResultAtom, (prev) => ({ ...prev, loading: true }));
      try {
        const response = await fetch(url);
        const data = await response.json();
        set(fetchResultAtom, { loading: false, error: null, data });
      } catch (error) {
        set(fetchResultAtom, { loading: false, error, data: null });
      }
    };

    fetchData();
  }
);

fetchAtom.onMount = (set) => {
  set("https://jsonplaceholder.typicode.com/todos/1");
};
// index.tsx
import { useAtomValue } from "jotai";

const result = useAtomValue(fetchAtom);

이제 loading, error, data 가 잘 나오는 것을 확인할 수 있다.


이외에도 Jotai 에서는 react-query 과 함께 사용하는 atomsWithQuery, atomsWithMutation, SSR 시 사용되는 useHydrateAtoms 등 여러 기능들을 제공하기에 필요시 그때그때 찾아서 개발하면 될 것 같다.

profile
개발자 Hoon입니다

0개의 댓글