概要
Expo SDK 53が出たのでアップデートしたら、合わせてReact 19にアップデートされた。
以前から使用していたRecoilはReact 19をサポートしていないので、Zustandに移行したので記事にした。
PR
Zustandとは
- Zustandはグローバルステートを管理するライブラリ
- 軽量でシンプルなコードで実装できるのが特徴
- 今回導入したアプリは、元からグローバルステートは最低限の実装しかなったので、一番シンプルなZustandを採用
- 内部ストアの仕組みで
React Context APIを使用せず状態管理はReactからは独立している
ので、RecoilのようにReact依存で使用できなくることは避けられそうなのも採用した理由の1つ
実装
導入
以下のコマンドで導入。
pnpm add zustand
ステートの更新 & 取得との移行
Recoilのコード
Recoilで情報を管理したい場合は以下のように宣言。
import { atom } from "recoil"; import type { ItemQuery } from "@/queries/api/index"; export type Item = NonNullable<ItemQuery["item"]>; type HomeItems = { items: Item[]; }; const initialHomeItemsState = (): HomeItems => ({ items: [], }); export const homeItemsState = atom<HomeItems>({ key: "homeItemsState", default: initialHomeItemsState(), });
値を設定したい場合は以下のように記載。
import { useSetRecoilState } from "recoil"; import { homeItemsState } from "@/store/atoms"; const useHomeItems = () => { const setHomeItemsState = useSetRecoilState(homeItemsState); (略) useEffect(() => { if (prevLoading !== null && !loading) { const items = (data?.itemsByDate || []).map((v) => ({ id: v?.id || "", title: v?.title || "", categoryID: v?.categoryID || 1, date: v?.date || "", like: v?.like || false, dislike: v?.dislike || false, createdAt: v?.createdAt || "", updatedAt: v?.updatedAt || "", })); setHomeItemsState({ items }); // ←値を設定 setApiLoading(false); } }, [loading, prevLoading, setHomeItemsState, data]);
値を設定取得したい場合は以下のように記載。
■features/home/components/Connected.tsx
import { homeItemsState } from "@/store/atoms"; import { useRecoilValue } from "recoil"; const Connected: React.FC<Props> = (props) => { const homeItems = useRecoilValue(homeItemsState); // ←値を取得
Zustandのコード
Zustandでユーザーの情報を管理したい場合は以下のように宣言。
import type { ItemQuery } from "@/queries/api/index"; import { create } from "zustand"; export type Item = NonNullable<ItemQuery["item"]>; type HomeItems = { items: Item[]; }; const initialHomeItemsState = (): HomeItems => ({ items: [], }); export const useHomeItemsStore = create<{ homeItems: HomeItems; setHomeItems: (items: Item[]) => void; reset: () => void; }>((set) => ({ homeItems: initialHomeItemsState(), setHomeItems: (items) => set({ homeItems: { items } }), reset: () => set({ homeItems: initialHomeItemsState() }), }));
値を設定したい場合は以下のように記載。
import { useHomeDateStore } from "@/store/homeDateStore"; const useHomeItems = () => { const setHomeItemsState = useHomeItemsStore((state) => state.setHomeItems); (略) useEffect(() => { if (prevLoading !== null && !loading) { const items = (data?.itemsByDate || []).map((v) => ({ id: v?.id || "", title: v?.title || "", categoryID: v?.categoryID || 1, date: v?.date || "", like: v?.like || false, dislike: v?.dislike || false, createdAt: v?.createdAt || "", updatedAt: v?.updatedAt || "", })); setHomeItemsState(items); // ←値を設定 setApiLoading(false); } }, [loading, prevLoading, setHomeItemsState, data]);
値を設定取得したい場合は以下のように記載。
■features/home/components/Connected.tsx
import { useHomeItemsStore } from "@/store/homeItemsStore"; const Connected: React.FC<Props> = (props) => { const homeItems = useHomeItemsStore((state) => state.homeItems); // ←値を取得
上記のコード修正でステートの更新と取得が可能になる。
まとめ
上記のコード修正でサクッと移行できたので次はExpo SDK 52 → 53移行を進めていく予定。