このドキュメントは、GROWIのページ遷移からレンダリングまでのデータフローを解説します。
[[...path]].page.tsx: Next.js の動的ルーティングを担うメインコンポーネント。サーバーサイドとクライアントサイドの両方で動作します。useSameRouteNavigation.ts: クライアントサイドでのパス変更を検知し、データ取得をトリガーするフック。useFetchCurrentPage.ts: データ取得と関連する Jotai atom の更新を一元管理するフック。データ取得が本当に必要かどうかの最終判断も担います。useShallowRouting.ts: サーバーサイドで正規化されたパスとブラウザのURLを同期させるフック。server-side-props.ts: サーバーサイドレンダリング(SSR)時にページデータを取得し、props としてページコンポーネントに渡します。ユーザーがURLに直接アクセスするか、ページをリロードした際のフローです。
/user/username/memo)を受け取ります。getServerSideProps の実行:
server-side-props.ts の getServerSidePropsForInitial が実行されます。retrievePageData が呼び出され、パスの正規化(例: /user/username → /user/username/)が行われ、APIからページデータを取得します。currentPathname) を props として [[...path]].page.tsx に渡します。[[...path]].page.tsx は props を受け取り、そのデータで currentPageDataAtom などのJotai Atomを初期化します。PageView などのコンポーネントがサーバーサイドでレンダリングされます。useShallowRouting が実行され、ブラウザのURL (/user/username/memo) と props.currentPathname (/user/username/memo/) を比較します。router.replace を shallow: true で実行し、ブラウザのURLをサーバーが認識している正規化後のパスに静かに更新します。<Link> クリック時)アプリケーション内でページ間を移動する際のフローです。
<Link href="/new/page"> をクリックします。useRouter がURLの変更を検出し、[[...path]].page.tsx が再評価されます。useSameRouteNavigation によるトリガー:
useEffect が router.asPath の変更 (/new/page) を検知します。fetchCurrentPage({ path: '/new/page' }) を呼び出します。このフックは常にデータ取得を試みます。useFetchCurrentPage によるデータ取得の判断と実行:
fetchCurrentPage 関数が実行されます。path をデコードします(例: encoded%2Fpath → encoded/path)。/65d4e0a0f7b7b2e5a8652e86)かどうかを判定します。pageLoadingAtom を true に設定します。apiv3Get('/page', ...) を実行してサーバーから新しいページデータを取得します。パラメータには、パス、ページID、リビジョンIDなどが含まれます。currentPageDataAtom, currentPageEntityIdAtom, currentPageEmptyIdAtom, pageNotFoundAtom, pageLoadingAtom など)。pageIdがundefinedになるなど)が発生することなく、データが完全に揃った状態で一度だけ状態が更新されます。pageErrorAtom にエラーオブジェクトを設定します。pageNotFoundAtom を true に設定します。pageLoadingAtom を false に設定します。PageView の最終レンダリング:
currentPageDataAtom の更新がトリガーとなり、PageView コンポーネントが新しいデータで再レンダリングされます。useSameRouteNavigation 内で fetchCurrentPage が完了した後、mutateEditingMarkdown が呼び出され、エディタの状態が更新されます。