home / blog / useContextでの状態管理をsessionStorageに保存する

useContextでの状態管理をsessionStorageに保存する

useContextでタブの選択状態をwebアプリ全体に共有している。これを、リロードしても保持されるようにブラウザのsessionStorageに保存します。

該当のファイル : https://github.com/kanaru-ssk/pay-history/blob/main/src/hooks/tabStatus.tsx

useContextの設計

useStateで管理するtabStatusと、それを更新する関数をcontextで共有する。

const [tabStatus, setTabStatus] = useState<TabStatus>()

sessionStorageはkey – valueの形で保存するため、keyを定義しておく。

const key = "tabStatus";    // sessionStorageに保存するkey

stateを更新する関数を拡張して、更新するたびにsessionStorageに保存するようにする。

// stateを更新する関数を拡張
const expandedSetTabStatus = (tab: TabStatus) => {
    setTabStatus(tab);
    sessionStorage.setItem(key, JSON.stringify(tab));    // sessionStorageにtabを保存
  };

sessionStorageにtabStatusが保存されている場合は初期値に設定する。

定義されていない時は適当な値を入れる。今回はその日の月を数値で入れている。

  const [tabStatus, setTabStatus] = useState<TabStatus>(() => {
    // sessionStorageにtabStatusが保存されている場合は初期値に設定
    const value = sessionStorage.getItem(key);
    return value ? JSON.parse(value) : new Date().getMonth() + 1;
  });

ProviderでtabStatusと、拡張した更新関数を共有

<TabStatusContext.Provider
      value={{ tabStatus: tabStatus, setTabStatus: expandedSetTabStatus }}
    >
      {children}
    </TabStatusContext.Provider>

これでsessionStorageへの共有は完了ですが、NextJSだとSSR機能によってサーバーサイドでsessionStorageが実行され、window is not defined とエラーになってしまう。

そこで、Providerを呼び出す側に変更を加える。

該当のファイル : https://github.com/kanaru-ssk/pay-history/blob/main/src/pages/_app.tsx

sessionStorageのコードがサーバーサイドで実行されないように、dynamic importを使用。

公式リファレンス : https://nextjs.org/docs/advanced-features/dynamic-import

const MyApp = ({ Component, pageProps }: AppProps) => {

  // Providerをダイナミックインポート
  const DynamicTabStatusProvider = dynamic(() => import("hooks/tabStatus"), {
    ssr: false,
  });

  return (
    <DynamicTabStatusProvider>
      <Component {...pageProps} />
    </DynamicTabStatusProvider>
  );
};

以上。