9. parallel routes
Page ごとに Header を変更する
下記のように、Page ごとに Header を変更できるようにしてみましょう。
| inbox | draft |
|---|---|
![]() | ![]() |
今回は、parallel routes を利用して、Page ごとに Header を変更する方法を紹介します。
実装する
apps/workspace/app/(dashboard)/layout.tsx を下記のように変更します
// apps/workspace/app/(dashboard)/layout.tsxexport default function dashboardLayout(props: { children: React.ReactNode; header: React.ReactNode;}) { return ( <main className="relative"> <div className="p-8 h-dvh"> <div className="flex items-center justify-between"> <h1 className="text-4xl font-extrabold tracking-tight"> The Joke Mail Service {props.header} </h1> <form action={logout}>次に、apps/workspace/app/(dashboard)/@header/inbox/page.tsxを新規で作成します。
mkdir -p "apps/workspace/app/(dashboard)/@header/inbox"touch "apps/workspace/app/(dashboard)/@header/inbox/page.tsx"export default function Header() { return "The Joke Mail Service | Inbox";}この時点で、http://localhost:3000/inbox にアクセスすると、Header が The Joke Mail Service | Inbox に変更されます。
つぎに、http://localhost:3000/drafts にアクセスしてみてください。404エラーが表示されると思います。
これは、@headers という形で分割された先にPageが存在しないためです。
draftも同様に追加してみましょう。
mkdir -p "apps/workspace/app/(dashboard)/@header/drafts"touch "apps/workspace/app/(dashboard)/@header/drafts/page.tsx"export default function Header() { return "The Joke Mail Service | Drafts";}これで http://localhost:3000/drafts にアクセスしても、404が表示されなくなったと思います。
ここで「すべてのページに追加しなければならないのか?」と思うかもしれません。
実は、存在しないPageにアクセスした場合のために、default.tsx をつかって、デフォルトのHeaderを表示することができます。
実際にdefault.tsx を作成してみましょう。
touch "apps/workspace/app/(dashboard)/@header/default.tsx"export default function Header() { return "The Joke Mail Service";}これで、http://localhost:3000/sentにアクセスした場合には、The Joke Mail Service が表示されるようになっていると思います。
parallel routes の仕様について理解する
ここで少し不思議な現象を確認してみましょう。
まず、http://localhost:3000/inbox にアクセスしてみてください。
その後、サイドバーから、`Sent` Button クリックして、http://localhost:3000/sent にアクセスしてみてください。
すると、Header が The Joke Mail Service | Inbox のまま変更されないことを確認できると思います。
また、その場でリロード(または、直接アクセス)すると、Header が The Joke Mail Service に変更されることを確認できると思います。
これは parallel routes の仕様です。
ソフトナビゲーション(Next Link)では、遷移先の URL と一致するサブページ(今回でいうと@header/sent/page.tsx)がなくても、現在のサブページを維持して遷移します。
ハードナビゲーション(ブラウザーのリロードや直接アクセスされた時) では、 URL と一致するサブページがない場合は、default.js が表示されます。default.js がない場合は、404 が表示されます。
「結局すべてのページに追加しなければならないのか?」と思うかもしれません。
catch-all route を使うことで解決することができます。
catch-all route は、[...catchAll]/page.tsx という形で指定することができます。どれにもマッチしない場合はこのページが表示されます。
これは、default.tsx よりも優先されます。
mkdir -p "apps/workspace/app/(dashboard)/@header/[...catchAll]"touch "apps/workspace/app/(dashboard)/@header/[...catchAll]/page.tsx"//apps/workspace/app/(dashboard)/@header/[...catchAll]/page.tsxexport default function Header() { return "The Joke Mail Service";}これで、http://localhost:3000/sentにアクセスした場合には、The Joke Mail Service が表示されるようになっていると思います。
まとめ
今回は、parallel routes を利用して、Page を分割する方法を紹介しました。
parallel routes を利用することで、Layout をより柔軟に設計することができます。
Next.js 15 rc
Next.js 15 rc では、parallel routes でも chatch-all route の path params を引数として受け取ることができるようになりました。
cd apps/solution/pnpm install next@rc react@rc react-dom@rccd ../../pnpm dev//apps/solution/app/(dashboard)/@header/[...catchAll]/page.tsxexport default function Header(props: { params: { catchAll: string[] } }) { return `The Joke Mail Service | ${props.params.catchAll.join(' | ')}`;}
