🧠
Nuxt3のuseStateの値をlocalStorageを使って永続化する
以下を参考にしてNuxt3バージョンを作ったメモです。
ページを更新したりブラウザを開き直しても保持される変数を作ります。
以下のように useState
のラッパークラスを1つ用意します。
composables/persist.ts
export const usePersistState = <T>(key: string, init: () => T): Ref<T> => {
const initResult: T = init()
let storedValue = null
try {
storedValue = JSON.parse(localStorage.getItem(key) + '') // nullはkey無し・空文字列はkey有り
} catch { }
// nullなら新規追加
if (storedValue === null) localStorage.setItem(key, JSON.stringify(initResult))
// 現在のstateに追加
const refs: Ref<T> = useState<T>(key, () => ((storedValue !== null) ? storedValue : initResult) as T)
// 変更検知
watch(refs, newValue => localStorage.setItem(key, JSON.stringify(newValue)))
return refs
}
export const removePersistState = (key: string): boolean => {
const exist = localStorage.getItem(key)
localStorage.removeItem(key)
return (exist !== null)
}
これをcomponentsの中で使います。
components/menu.vue
<script setup lang="ts">
const debugMode = usePersistState<boolean>('debug_mode', () => true)
</script>
<template>
<div>
<h3>デバッグ表示</h3>
<input id="debugSwitch" type="checkbox" v-model="debugMode.value">
</div>
</template>
これは以下のような設定値を切り替えるトグルスイッチの例ですが、ページを更新したりタブやブラウザを閉じて開き直しても値が保持されるようになります。文字列や数値でも同様に使えます。
補足
- SSRのことは考慮できてないので、両方でレンダリングが発生するような場合はブラウザ側でのみlocalStorageが動くように作り替える必要があります。
- Nuxt3のuseStateについて基本的なことはこちら。
Discussion