recoilの永続化 Recoil Persist

作成:2022/10/09
更新:2022/10/14

Recoil Persistで簡単にできるけど保存場所だけ注意

問題

index.tsxで取得したデータをヘッダーに渡したいが、LayoutコンポーネントにHeader入れてるのでバケツリレーがやばい。
ヘッダーの表示をRecoilに保存した配列から生成した。
トップページ以外でリロードするとStateが消えるのでヘッダーの表示も消える。

解決

そもそもSSGしたいわけだからgetStaticPropsするしかない?
永続化自体はRecoil Persistで簡単にできた

Recoil Persist
https://github.com/polemius/recoil-persist

+import { recoilPersist } from "recoil-persist";
+const { persistAtom } = recoilPersist();

export const categoryAtom = atom<ParentCategoriesEntity[]>({
    key: "category",
    default: [],
    +effects_UNSTABLE: [persistAtom],
});


注意点 保存場所がlocalStorage

After this each changes in atom will be store and sync to localStorage.



ただこのままだとエラーが。
Warning: Cannot update a component (Batcher) while rendering a different component (`Home`). To locate the bad setState() call inside `Home`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render

いろいろやってもハイドレーションのエラーが出まくる。
下記2つでとりあえずエラーは消えたけども。Headerの表示が遅いのダメすぎる。
片方だけだとエラーが出る。

useEffect(() => {
    setCategoryState(category);
}, []);


//Layout.tsx
const Header = dynamic(() => import("./Header"), {
    ssr: false,
});


結局全部のページでgetStaticPropsして、Layout>Headerでバケツリレーした。


参照

React Hooks: 子コンポーネントから親の状態をレンダー時に変えたら叱られた ー Warning: Cannot update a component while rendering a different component
https://qiita.com/FumioNonaka/items/3fe39911e3f2479128e8