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>
);
};
以上。