状態を localStorage と同期する
React の状態と localStorage を双方向に同期する useLocalStorage カスタムフックを作成します。
「状態を localStorage と同期する」はCoddyKit上の無料React Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。
素朴なアプローチでは同期がずれる
最初に思いつく方法は、ある場所でlocalStorageを読み取り、別の場所で書き込むことですが、これらは次第に食い違う可能性があります。状態の更新時に保存を忘れたり、保存された値が状態に反映されなかったりすると、バグにつながります。
Reactの状態とストレージを常に一致させる、信頼できる唯一の情報源が必要です。
useLocalStorageカスタムフック
すっきりした解決策は、useStateをラップして変更を自動的に保存するuseLocalStorageフックです。useStateと同じように、値とセッターを返します。
利用側は通常の状態とまったく同じように使えますが、保存機能も自動的に得られます。
遅延初期化関数
localStorageの読み取りは同期処理なので、レンダーのたびに実行してはいけません。useStateに関数、つまり遅延初期化関数を渡すことで、マウント時に一度だけ読み取りを実行できます。
その関数内で保存された値をパースし、失敗した場合は指定されたデフォルト値を返します。
遅延初期化が重要な理由
初期状態を引数として直接計算すると、その式は初回以降は無視されるにもかかわらず、レンダーのたびに実行されます。関数を渡すと、Reactはその関数を一度だけ呼び出します。
localStorageの読み取りでは、これによりレンダーごとにメインスレッドで同期処理を繰り返すことを避けられます。
useEffectによる同期
更新を保存するには、値が変わるたびに実行され、localStorage.setItem(key, JSON.stringify(value))を呼び出すuseEffectを追加します。
依存配列に値を入れると、状態が変わるたびにストレージへ自動的に書き込まれます。
関数型更新で古いクロージャを回避
前の値を基に設定する場合は、setValue(prev => prev + 1)のような関数型の形式を使います。これにより、古い値をキャプチャして書き込んでしまう、古いクロージャの問題を避けられます。
特に、古いスナップショットをキャプチャする可能性があるイベントハンドラーやエフェクト内では重要です。
保存値がnullの場合の処理
キーが存在しない場合、getItemはnullを返します。初期化関数ではこれを検出し、nullをパースしようとせずにデフォルト値へフォールバックする必要があります。
stored != null ? JSON.parse(stored) : defaultValueのようなガードを使うと、初回訪問時も適切に処理できます。
TypeScriptのジェネリック
TypeScriptでは、フックをジェネリックにします。function useLocalStorage<T>(key: string, initial: T)のように記述すると、値の型が保持され、利用側で完全な型安全性を得られます。
返されるタプルは[T, Dispatch<SetStateAction<T>>]として型付けされ、useStateと一致します。
保存データのバージョン管理
時間が経つとデータの形は変化し、古い保存値が新しいコードを壊す可能性があります。データとともにバージョンキーも保存し、古い形式を検出できるようにします。
たとえば{ version: 2, data }を保存し、読み取り時にバージョンを比較します。
バージョン不一致時の削除
保存されたバージョンが現在のものと一致しない場合は、その古い値をそのまま信頼せず、破棄するか移行します。最も単純な方法は、古いエントリを削除してデフォルト値にフォールバックすることです。
これにより、アプリの古いリリースが書き込んだデータによるクラッシュを防げます。
フックを組み立てる
完全なuseLocalStorageは、安全に読み取りとパースを行う遅延初期化関数、関数型更新に対応したセッター、そしてバージョン管理付きで書き込むuseEffectを組み合わせたものです。
その結果、再読み込み後も状態を保持できる、useStateのドロップイン置換になります。
理解度チェック
状態の初期化について理解度を確認しましょう。
まとめ
遅延初期化関数を使ったuseLocalStorageフックの構築、useEffectによる変更の保存、古いクロージャを避ける関数型更新、null値の処理を学びました。
さらに、古いデータを安全に削除するためのTypeScriptのジェネリックとバージョン管理についても学びました。
よくある質問
「状態を localStorage と同期する」レッスンは無料ですか?
はい。「状態を localStorage と同期する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。
「状態を localStorage と同期する」で何を学びますか?
React の状態と localStorage を双方向に同期する useLocalStorage カスタムフックを作成します。 ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「状態を localStorage と同期する」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- React で localStorage を読み書きする
- 状態を localStorage と同期する
- タブ間で Storage イベントを処理する
- sessionStorage、IndexedDB、適切な API の選び方