🧎
zustandでLocal Storageから取得した値を待つ
はじめに
Next.jsで状態管理に zustand
を使い、Local Storageから取得した値を判定して処理の分岐をしたときの記録です。
サンプルコードは、ファイル内の全コードではなく注目箇所だけ書いていますのでご注意ください。
分岐処理の概要
画面で以下のような分岐処理を実装していました。
pages.tsx
// Local Storageに保存したidの値を取得
const id = useStore(useIdStore, (state) => state.id);
// id === undefinedなら別ページに遷移
useEffect(() => {
if (id === undefined) router.push('/another-page')
}, [id])
問題点
id
の初期値は undefined
にしていて、id
を取得した時の値は以下の3パターンになります。
(a) Local Storageから id
を取得中・・・ id = undefined
(b) idが登録されていない・・・ id = undefined
(c) idが登録されている・・・ id = 'xxxxxxxxxxxxxxxx'
(a)の変数取得中の時間があり、id
が存在していても id === undefined
の条件が発動してしまうのが問題でした。
解決法1
storeでgetterを使って、その関数に対して判定処理をすることで、戻り値を待ってから判定されるようにしました。
IdStore.ts
export const useIdStore = create<State & Action>()(
persist(
(get) => ({
getId: () => {
get().id;
},
}),
{
name: "id-storage",
}
)
);
解決法2
Local Storageに id
が保存されていない場合は id = ''
を最初にセットするための初期化関数を作り、undefined
''
'xxxxxxxxxxxxxxxx'
の3つの状態を作るようにしました。
この場合は、getterではなく直接変数の値を取得しています。
IdStore.ts
export const useIdStore = create<State & Action>()(
persist(
(set, get) => ({
id: undefined,
initId: () => {
if (get().id === undefined) set(() => ({ id: "" }));
},
}),
{
name: "id-storage",
}
)
);
pages.tsx
// Local Storageに保存したidの値を取得
const id = useStore(useIdStore, (state) => state.id);
const initId = useStore(useIdStore, (state) => state.initId);
// Local Storageにidが存在しなかったら初期化
useEffect(() => {
initId()
}, [initId])
// id === ''なら別ページに遷移
useEffect(() => {
if (id === '') router.push('/another-page')
}, [id])
おわりに
記事用にコードをコンパクトに新しく書いているため、間違いなどあればお知らせください。
Discussion