対象読者
- JavaScriptとWeb開発の基礎に理解がある方
- Reactを用いたJavaScriptアプリケーション開発の経験者
前提環境
筆者の検証環境は以下の通りです。
- macOS Ventura 13.4
- Node.js 20.6.1/npm 9.8.1
- React 18.2.0
- Next.js 13.4.19
Nested Routesでページ内の一部分だけを別のファイルで定義する
前回はHacker Newsの最新20件を読めるアプリケーションを途中まで作り、メニューが表示できるようになりました。図1のように、idがsidebar
になっているメニュー部分と、コンテンツを表示する予定の<main>
要素で構成されています。
メニューを作ったので、次はメニューの項目をクリックしたときに、<main>
要素にある本文に記事を表示したいですね。具体的には、/top20/xxxxxx
のようなURLへアクセスしたときに、本文が表示されると嬉しいです。
こういった挙動を作るときに役立つのが、Nested Routes(ネステッドルーツ)と呼ばれる機能です。ルート(ページ)の定義をネスト(入れ子)にすることで、画面遷移の際にページ内の一部分だけを更新することができます。
1つのページのレイアウトを複数のファイルで構成する
実際の挙動を見たほうが早いので、手を動かしてみましょう。まずは、前回作った/top20/page.js
をリネームして、/top20/layout.js
にします。layout.js
はApp Routerのファイルとフォルダによるルーティングにおける予約されたファイル名のひとつで、レイアウトという機能を実現するためのものです。
続けて、ファイル内にも少し手を入れます(リスト1)。
// (省略) export default async function Top20Layout({ children }) { // (1) // (省略) <main> {children}{/* (2) */} </main> // (省略)
まずは、(1)の変更です。ファイル名に合わせて、コンポーネント名をTop20Page
からTop20Layout
に変更しました。また、propsとしてchildren
を取り出しています。(2)では、そのchildren
を<main>
要素の中で展開しています。図1の時点では<div>本文をここに表示する</div>
テキストを仮置きしていた部分ですね。
このchildren
は、いわゆるプレースホルダーとして機能します。アクセスするURLのパスに応じて、別のファイルで定義したコンポーネントに差し変わります。といっても、どんなパスでも差し替えられるわけではありません。このlayout.js
が設置されたフォルダ以下の階層に配置されたページがchildren
に表示されうるものになります。つまり、app/top20/
以下に配置したpages.js
やlayout.js
などの外側に、リスト1のレイアウトが被さるイメージになります。
さて、App Routerはpage.js
が置いてあるフォルダパスをアプリケーションのURLパスとして成立させる仕組みなので、page.js
が不在のままにしておくわけにはいきません。改めてapp/top20/page.js
を作りましょう(リスト2)。
import "./_style/article.css"; // (1) export default function Top20IndexPage() { return ( <article> <p>ここに記事が表示されます。</p> <p>左のメニューから記事を選択してください。</p> </article> ); }
特段複雑なことをしない、静的な表示です。(1)のarticle.css
は、サンプルコードの中にあるので、必要な方はコピーしておいてください。この時点で、appフォルダの中は図2のようになりました。
では、この状態でhttp://localhost:3000/top20
を確認してみましょう(図3)。
children
を配置した場所に、リスト2で実装したapp/top20/page.js
の内容が表示されました。ルート(≒ページ)の中にルートを表示する仕組みであり、Nested Routesと呼ばれています。
この状態では、Nested Routesの真価はまだ発揮されていません。前述のとおりapp/top20/layout.js
という外側のレイアウトを司るファイルはapp/top20/
フォルダ配下のすべての表示可能なファイルに対して適用されるのです。app/top20/page.js
でも、それ以外のファイルでも、同じようにapp/top20/layout.js
が外側のレイアウトとして表示され続けることに真価があります。つまり、/top20/xxxxxx
のようなパスを表示するときにも、サイドメニューを表示させ続けることができるのです。