Next.jsのParallel Routeの挙動を理解する
はじめに
Next.jsのApp RouterではParalell Routesという機能が利用できます。
機能の説明については公式ページで詳しく解説されていますが、実際にページ遷移した際にどのコンポーネントがレンダリングされるか等、自分は曖昧にしか理解できていませんでした。
そこで、今回はParalell Routesによってどのコンポーネントがレンダリングされているか確認するためのアプリを作って、挙動を確かめてみることにしました。
前提
Paralell Routesの機能自体については、公式ページにて説明されていますが、準備も含めて、簡単にここでおさらいしておきます。今回は以下のような構成のアプリを想定します。
// app/以下のファイル構成
├── layout.tsx
├── default.tsx
├── page.tsx
├── @left
│ ├── default.tsx
│ ├── page.tsx
│ └── groups
│ └── page.tsx
├── @right
│ ├── default.tsx
│ ├── page.tsx
│ └── users
│ └── page.tsx
Parallel Routesでは、接頭に@
がつくSlotと呼ばれるディレクトリを用意し、layout.tsx
においてslotを任意の位置にrederします(Slotはディレクトリですが、ルート扱いされません)。
type Props = {
children: React.ReactNode;
left: React.ReactNode;
right: React.ReactNode;
}
const Layout: FC<Props> = ({ children, left, right }) => {
return (
<html lang="en">
<body className={inter.className}>
{children}
{left}
{right}
</body>
</html>
);
}
このように配置することで、同じlayout内で、3つのルート/
, /groups
, /users
に対して、それぞれ状況に応じた **/defaults.tsx
, **/page.tsx
がrenderされることになります。
(ややこしく曖昧な表現になっていますが、以降の章で解説します🙇)。
検証
Parallel Routesは、状況に応じてどのファイルがrenderされるのか、このパターンが非常に混乱しやすいと自分は思います。
そのため今回は、現在のパスとrenderされているファイル、そのrender結果を同時に表示できるような検証用アプリを用意しました。
以降では、それぞれのルートに遷移した際にどのファイルがrenderされるのかを、このアプリで見ていきたいと思います。
/を開いた時
まず、ユーザーが/
に訪れた際に表示されるページです。
それぞれの**/page.tsx
が表示されていることがわかると思います。最もシンプルなケースですね。
/groupsに遷移した時
次に、/
から/groups
に遷移してみます。
すると、/@left/page.tsx
が/@left/groups/page.tsx
に変わりました。こちらは想定通りですが、他のファイルについては遷移前から変わりません。パスが/groups
なのにも関わらず、/page.tsx
がrenderされているのは少し違和感があります。
この挙動については、公式のページに記載があります。
Soft Navigation: During client-side navigation, Next.js will perform a partial render, changing the subpage within the slot, while maintaining the other slot's active subpages, even if they don't match the current URL.
こちらによると、/
から/groups
の遷移では、Soft Navigationが行われ、この場合/page.tsx
など、遷移後のパスとマッチしない場合であっても、Slot内のページは維持されるようです。
※/page.tsx
もLayout.tsxから見たとき、children=Slotの一つとなります。
/groupsをリロードした時
次に、現在のページである/groups
をリロードしてみます。
すると今度は、/page.tsx
と/@right/page.tsx
がそれぞれ/default.tsx
と/@right/default.tsx
に変わりました。こちらの挙動についても公式に記載があります。
Hard Navigation: After a full-page load (browser refresh), Next.js cannot determine the active state for the slots that don't match the current URL. Instead, it will render a default.js file for the unmatched slots, or 404 if default.js doesn't exist.
/groups
をリロードした場合、Hard Navigationが行われます。
この場合、リロード前に表示されていた/page.tsx
などの現在のルートとはマッチしないサブページでは、default.tsx
がrenderされる挙動となるようです(defaults.tsx
がない場合404となる)。
/groupsから/usersに遷移した時
最後に、/groups
から/users
に遷移してみます。
すると、/default.tsx
と/@left/groups/page.tsx
はそのままですが、/@right/default.tsx
は/@right/users/page.tsx
に変化しました。今回はSoft Navigationであるため、/groups
に遷移した時と同じパターンの遷移になっているかと思います。なんとなく、わかってきましたね。
まとめ
今回作成したアプリで、Parallel Routesによる以下の挙動が確認できました。
- Soft Navigationによって遷移した場合、一度訪れたSlot内のサブページは維持される
- ページリロードなどでHard Navigationが行われると、パスにマッチしないルートは
default.tsx
が表示される(defaults.tsx
がない場合404となる)
このParallel Routesは公式ページにもある通り、ダッシュボードやModalで、遷移済みのサブページを維持しつつ別のサブページを表示したい時などに便利な機能になるかと思います。
(※ModalではIntercepting Rotesと組み合わせて使う必要があります)
最後に
ここまで読んでいただきありがとうございます🙇
実際に動く環境とコードはそれぞれ以下で公開しています。
動作環境:https://parallelroute-sample-ypin.vercel.app/
コード:https://github.com/mktu/parallelroute-sample
Discussion