ページとレイアウト
Next.js 13 の App Router では、ページ、共有レイアウト、テンプレートを簡単に作成できる新しいファイル規約が導入されました。このページでは、Next.js アプリケーションでこれらの特殊ファイルを使う方法を説明します。
ページ
ページとは、ルートに固有の UI です。page.js
ファイルからコンポーネントをエクスポートすることで、ページを定義できます。ネストされたフォルダを使用してルートを定義し、page.js
ファイルを使用してルートに一般的にアクセスできるようにします。
app
ディレクトリ内に page.js
ファイルを追加して、最初のページを作成します:
// `app/page.tsx` is the UI for the `/` URL
export default function Page() {
return <h1>Hello, Home page!</h1>
}
// `app/dashboard/page.tsx` is the UI for the `/dashboard` URL
export default function Page() {
return <h1>Hello, Dashboard Page!</h1>
}
Good to know:
- ページは常にルートサブツリーのリーフです。
.js
,.jsx
,.tsx
の拡張子をページに使用することができます。page.js
ファイルはルートセグメントを一般公開するために必要です。- ページはデフォルトではServer Componentsですが、Client Componentに設定することもできます。
- ページはデータをフェッチすることができます。詳細はData Fetchingセクションを参照してください。
レイアウト
レイアウトは、複数のページ間で共有される UI です。ナビゲーションの際、レイアウトは状態を保持し、インタラクティブであり続け、再レンダリングしません。レイアウトは入れ子にすることもできます。
レイアウトを定義するには、layout.js
ファイルからdefault
React コンポーネントをエクスポートします。このコンポーネントは children
prop を受け取る必要があり、レンダリング時に子レイアウト(存在する場合)または子ページが入力されます。
export default function DashboardLayout({
children, // will be a page or nested layout
}: {
children: React.ReactNode
}) {
return (
<section>
{/* Include shared UI here e.g. a header or sidebar */}
<nav></nav>
{children}
</section>
)
}
Good to know:
- 一番上のレイアウトはルートレイアウトと呼ばれます。この必須レイアウトは、アプリケーション内のすべてのページで共有されます。ルートレイアウトは
html
とbody
タグを含まなければなりません。- 任意のルートセグメントはオプションで独自のLayoutを定義することができます。これらのレイアウトはそのセグメント内のすべてのページで共有されます。
- ルート内のレイアウトはデフォルトで 入れ子 になっています。それぞれの親レイアウトは、React の
children
prop を使用して、その下の子レイアウトをラップします。- Route Groupsを使って、特定のルートセグメントを共有レイアウトに入れたり入れたりすることができます。
- レイアウトはデフォルトではServer Componentsですが、Client Componentに設定することができます。
- レイアウトはデータをフェッチすることができます。詳細はData Fetchingセクションを参照してください。
- 親レイアウトとその子レイアウトの間でデータを渡すことはできません。しかし、ルート内で同じデータを複数回フェッチすることは可能で、React はパフォーマンスに影響を与えることなくリクエストを自動的にデデュープします。
- レイアウトは現在のルートセグメントにアクセスできません。ルートセグメントにアクセスするには、クライアントコンポーネントで
useSelectedLayoutSegment
またはuseSelectedLayoutSegments
を使うことができます。.js
,.jsx
,.tsx
の拡張子をレイアウトに使用することができます。layout.js
とpage.js
ファイルを同じフォルダに定義することができます。レイアウトはページをラップします。
ルートレイアウト (必須)
ルートレイアウトは app
ディレクトリのトップレベルで定義され、すべてのルートに適用されます。このレイアウトによってサーバーから返される最初の HTML を修正できます。
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Good to know:
app
ディレクトリにはルートレイアウトが必要です。- ルートレイアウトには、
<html>
タグと<body>
タグを定義する必要があります。- ビルドイン SEO サポートを使って、
<head>
HTML 要素、たとえば<title>
要素を管理することができます。- ルートグループを使って複数のルートレイアウトを作成することができます。例はこちらを参照してください。
- ルートレイアウトはデフォルトではServer Componentであり、Client Componentには設定できません。
pages
ディレクトリからの移行: ルートレイアウトは_app.js
と_document.js
ファイルを置き換えます。移行ガイドを見る。
レイアウトの入れ子
フォルダ内で定義されたレイアウト (例 app/dashboard/layout.js
) は特定のルート Segment (例 acme.com/dashboard
) に適用され、それらの Segment がアクティブなときにレンダリングされます。デフォルトでは、ファイル階層内のレイアウトは nested で、children
プロップを通して子レイアウトをラップします。
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
Good to know:
- ルートレイアウトだけが
<html>
タグと<body>
タグを含むことができます。
上記の 2 つのレイアウトを組み合わせるとすると、ルートレイアウト(app/layout.js
)はダッシュボードレイアウト(app/dashboard/layout.js
)をラップし、ルート Segment は app/dashboard/*
内でラップされます。
2 つのレイアウトはこのように入れ子になります。
Route Groupsを使って、特定のルート Segment を共有レイアウトに出し入れできます。
テンプレート
テンプレートは各子レイアウトやページをラップするという点で、レイアウトに似ています。ルートにまたがって永続的に状態を維持するレイアウトとは異なり、テンプレートはナビゲーションの際に子要素ごとに新しいインスタンスを生成します。つまり、ユーザーがテンプレートを共有するルート間をナビゲートすると、コンポーネントの新しいインスタンスがマウントされ、DOM 要素が再作成され、ステートは保存されず、エフェクトは再同期されます。
そのような特定の動作が必要な場合があり、テンプレートはレイアウトよりも適切なオプションです。例えば
useEffect
に依存する機能(ページビューのロギングなど)やuseState
に依存する機能(ページごとのフィードバックフォームなど)。- デフォルトのフレームワークの動作を変更する。例えば、レイアウト内のサスペンスバウンダリは、レイアウトが最初に読み込まれたときのみフォールバックを表示し、ページを切り替えたときはフォールバックを表示しません。テンプレートの場合、フォールバックはナビゲーションごとに表示されます。
テンプレートは template.js
ファイルからデフォルトの React コンポーネントをエクスポートすることで定義できます。コンポーネントは children
プロパティを受け取る必要があり、これはネストされた Segment になります。
export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
レイアウトとテンプレートを持つルート Segment のレンダリング出力はこのようになります。
<Layout>
{/* Note that the template is given a unique key. */}
<Template key={routeParam}>{children}</Template>
</Layout>
<head>
の修正
app
ディレクトリでは、ビルドイン SEO サポート を使って title
や meta
のような <head>
HTML 要素を変更できます。
メタデータはlayout.js内のmetadata
objectまたはgenerateMetadata
関数をエクスポートすることで定義できます。 layout.js
またはpage.js
ファイルに記述します。
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
Good to know: ルートレイアウトに
<title>
や<meta>
のような<head>
タグを手動で追加すべきではありません。その代わりに、Metadata API を使うべきです。この API は<head>
要素のストリーミングや重複除去といった高度な要求を自動的に処理します。
利用可能なメタデータのオプションについてはAPI リファレンスを参照してください。