Open6
Next.js App Routerらしいコンポーネント最適解を見つける
ピン留めされたアイテム

下記に結果を記事化しました!

Next.js App Routerで利用される状態管理ライブラリ

グローバルステート系ライブラリの種類
Storeベース (トップダウン)
状態をStoreという一つのオブジェクトとして管理し、各コンポーネントから参照できる
- Redux
- zustand
Atomベース (ボトムアップ)
Storeベースとは異なり複数のAtomで状態管理を行い、各コンポーネントから複数のAtomを参照できる
- Recoil
- jotai
Proxyベース
プロキシは通常の JavaScript オブジェクトでありどこからでも変更可能
- Valtio
出典: https://react-uncle-blog.netlify.app/blog/react-state-managment
REF: https://zenn.dev/jotaifriends/articles/d714f9c16c1d3a?redirected=1

zustand vs jotai
zustand
- Star: 41K, Size: 1.2KB, Weekly download: 3.1M
- Storeベース (トップダウン) ※e.g. Redux
- 単一のストアが基本 (複数のストアを作ることもできる)
- Reactの外部でステートが管理される
- Storeが親でコンポーネントが子
- 単一方向のデータフロー
jotai
- Star: 16K, Size: 3.3KB, Weekly download: 861K
- Atomベース (ボトムアップ) ※e.g. Recoil
- 複数のストアを作れる
- Reactの内部でステートが管理される (useState + useContext)
- コンポーネントが親でAtomが子のような依存関係になる(?)
- 双方のデータフロー

App routerらしい最適解を見つける
課題1: 状態について
App routerでServer ComponentとClient Componentが分かれており、
単純にPages routerからApp routerへ移行しようとした際に、ステートの管理方法などを再検討しなければならず、
一旦、全てClient Componentで作るみたいなことが発生する。
最初に躓くServer Componentに移行する際に躓く主なポイントはこのステートの管理だと思う。
解決作成としては、主に下記の3点。
- クエリパラメータ/Cookieなどサーバー側で状態を管理できる方法利用する
- クエリパラメータ: ユーザー視点でどの状態のページでアクセスさせたいかを考え、ユーザーに取って有益であればクエリパラメータにデータを保管するのは有益に思える。一方で、例えばにヘッダーの開閉状態などユーザーに取って、無益なページのステータスはクエリパラメータに持たすべきではない。クエリパラメータが増えるということは、UXが悪くなるのは当然のこと、キャッシュの分散等にもつながるため注意。
- Cokkieを利用する: Cookieを読み出す場合、Next.jsはキャッシュを利用しなくなるため、パフォーマンス悪化につながるため、基本的には使わない方が良いと思う
- Composition Componentを利用する
- 基本的にClient ComponentからServer Componentを読み出すことは不可だが、Server Componentに読み込んだClient ComponentのchildrenにServer Componentを渡すことは可能。(Hydrationの仕組み)
- これを利用してClient Componentに逃がすComponentを最小化できる
- グローバルステートを利用する
- 基本的にグローバルステートを利用しない場合、StateのバケツリレーがClient Component -> Server Component間で途切れてしまい躓く。
- UIレイアウトとデータ層のコンポーネント設計を共存させるためにはグローバルステートによりコンポーネントのツリー外でステートを管理してあげる必要がある
課題2: Render as you fetchの最適解について
- fetchさせる場所について
- ページ全体で利用するpropsは、pagesでawait抜きでコールして、Promiseをpropsとして渡してあげるのが良さそう
- generateMetadataについて
- generateMetadata内でasync/await でメタデータを生成している場合、ページの初期レンダリングのボトルネックとなる。(generateMetadata -> page コンポーネントのレンダリングみたいな感じで同期的に処理される挙動に見える)
- このベストプラクティスは現状なし。

fetchさせる場所はコンポーネントの中で良さそうでした!