⛷️
zustandでstoreをストレージ管理
最近ReactNativeでzustandを使ってみました
簡単に状態管理ができて便利ですね
中でもストレージ管理が簡単でいいなと思いました
zustandで認証トークンをstore管理
storeをストレージ管理する例として、認証トークンを永続化することを考えます
以下はストレージ導入する前のコードです
認証APIを実行し、返り値(token)をstoreで管理します
import { create } from 'zustand';
type AuthState = {
token: string | null;
loading: boolean;
login: ({ id, password }: { id: string; password: string }) => void;
logout: () => void;
};
export const useAuth = create<AuthState>((set, get) => ({
token: null,
loading: false,
login: async ({ id, password }) => {
set({ loading: true });
await fetch('api/login', {
method: 'POST',
body: JSON.stringify({ id, password }),
})
.then((res) => res.json())
.then((data) => set({ token: data.token }))
.finally(() => set({ loading: false }));
},
logout: async () => {
set({ loading: true });
await fetch('api/logout', {
method: 'POST',
body: JSON.stringify({ token: get().token }),
})
.then(() => set({ token: null }))
.finally(() => set({ loading: false }));
},
}));
tokenをストレージに保存
storeデータをストレージに保存し、アプリ起動時に前回のデータを使いたい場合があります
これを実装する際はストレージのロード/保存処理等を書く必要はなく、設定の追記だけで目的の処理を行えます
具体的に、zustand/middleware
と@react-native-async-storage/async-storage
をインストールし、以下の様に修正を加えるとtoken
だけ永続化され、アプリ起動時に前回のtoken
が自動的にロードされます
import { create } from 'zustand';
+ import { persist, createJSONStorage } from 'zustand/middleware';
+ import AsyncStorage from '@react-native-async-storage/async-storage';
type AuthState = {
token: string | null;
loading: boolean;
login: ({ id, password }: { id: string; password: string }) => void;
logout: () => void;
};
export const useAuth = create<AuthState>()(
+ persist(
(set, get) => ({
token: null,
loading: false,
login: async ({ id, password }) => {
set({ loading: true });
await fetch('api/login', {
method: 'POST',
body: JSON.stringify({ id, password }),
})
.then((res) => res.json())
.then((data) => set({ token: data.token }))
.finally(() => set({ loading: false }));
},
logout: async () => {
set({ loading: true });
await fetch('api/logout', {
method: 'POST',
body: JSON.stringify({ token: get().token }),
})
.then((res) => set({ token: null }))
.finally(() => set({ loading: false }));
},
}),
+ {
+ name: 'auth-storage',
+ partialize: (state) => ({ token: state.token }),
+ storage: createJSONStorage(() => AsyncStorage),
+ }
+ )
);
上記のstoreデータについて、token
以外の値(loading
など)は永続管理したくありません
この場合、上記のpartialize: (state) => ({ token: state.token })
のように永続化したい値を指定してあげるとその値のみアプリ起動時にロードされるようです
所感
- 同じデータをstoreとストレージの両方で管理したい場合はよくあるため、上記のように一緒に定義してストレージのロード/更新のコードを省略できるのはとても楽ですね
- zustandのファイルは
src/hooks/useAuth.ts
みたいに他のhooksと一緒にしてしまっていいのかな - 変数を更新するちょっとした関数が多くなった場合はファイル分割ってできるんですかね
Discussion