レイアウトとテンプレート
特殊なファイル layout.js と template.js により、ルート間で共有されるUIを作成できます。このページでは、これらの特殊なファイルの使用方法と使用タイミングについて説明します。
レイアウト
レイアウトは、複数のルート間で共有される UIです。ナビゲーション時に、レイアウトは状態を保持し、インタラクティブで、再レンダリングされません。レイアウトはネストすることもできます。
layout.js
ファイルからデフォルトエクスポートされるReactコンポーネントを定義することでレイアウトを作成できます。このコンポーネントは、レンダリング中に子レイアウト(存在する場合)またはページで埋められるchildren
プロップを受け取る必要があります。
例えば、以下のレイアウトは /dashboard
と /dashboard/settings
ページで共有されます:
ルートレイアウト(必須)
ルートレイアウトはapp
ディレクトリのトップレベルで定義され、すべてのルートに適用されます。このレイアウトは必須で、html
とbody
タグを含める必要があり、サーバーから返される初期HTMLを変更できます。
レイアウトのネスト
デフォルトでは、フォルダ階層内のレイアウトはネストされており、children
プロップを介して子レイアウトをラップします。特定のルートセグメント(フォルダ)内にlayout.js
を追加することで、レイアウトをネストできます。
例えば、/dashboard
ルートのレイアウトを作成するには、dashboard
フォルダ内に新しいlayout.js
ファイルを追加します:
上記の2つのレイアウトを組み合わせると、ルートレイアウト(app/layout.js
)がダッシュボードレイアウト(app/dashboard/layout.js
)をラップし、app/dashboard/*
内のルートセグメントをラップします。
2つのレイアウトは次のようにネストされます:
補足:
- レイアウトには
.js
、.jsx
、または.tsx
の拡張子を使用できます。- ルートレイアウトのみが
<html>
と<body>
タグを含むことができます。- 同じフォルダ内に
layout.js
とpage.js
ファイルが定義されている場合、レイアウトはページをラップします。- レイアウトはデフォルトでサーバーコンポーネントですが、クライアントコンポーネントに設定できます。
- レイアウトはデータを取得できます。詳細はデータフェッチセクションを参照してください。
- 親レイアウトとその子間でデータを渡すことはできません。ただし、同じルートでデータを複数回フェッチでき、Reactは自動的にリクエストを重複排除し、パフォーマンスに影響を与えません。
- レイアウトは
pathname
にアクセスできません(詳細はこちら)。ただし、インポートされたクライアントコンポーネントはusePathname
フックを使用してパス名にアクセスできます。- レイアウトは自身の下のルートセグメントにアクセスできません。すべてのルートセグメントにアクセスするには、クライアントコンポーネントで
useSelectedLayoutSegment
またはuseSelectedLayoutSegments
を使用できます。- ルートグループを使用して、特定のルートセグメントを共有レイアウトに対してオプトインまたはオプトアウトできます。
- ルートグループを使用して、複数のルートレイアウトを作成できます。例はここを参照してください。
pages
ディレクトリからの移行: ルートレイアウトは_app.js
と_document.js
ファイルに取って代わります。移行ガイドはこちら。
テンプレート
テンプレートは、子レイアウトまたはページをラップするという点でレイアウトと似ています。レイアウトがルート間で保持され状態を維持するのに対し、テンプレートはナビゲーション時に子ごとに新しいインスタンスを作成します。つまり、ユーザーがテンプレートを共有するルート間を移動する場合、子の新しいインスタンスがマウントされ、DOMエレメントが再作成され、クライアントコンポーネントの状態は保持されず、エフェクトが再同期されます。
これらの特定の動作が必要な場合があり、テンプレートはレイアウトよりも適切な選択肢となります。例えば:
- ナビゲーション時に
useEffect
を再同期する場合 - ナビゲーション時にクライアントコンポーネントの子の状態をリセットする場合
テンプレートは、template.js
ファイルからデフォルトでReactコンポーネントをエクスポートすることで定義できます。このコンポーネントはchildren
プロップを受け取る必要があります。
ネスト構造について、template.js
はレイアウトと子の間でレンダリングされます。簡略化された出力は次のとおりです:
例
メタデータ
メタデータAPIを使用して、title
やmeta
などの<head>
HTMLエレメントを変更できます。
メタデータは、layout.js
またはpage.js
ファイルでmetadata
オブジェクトまたはgenerateMetadata
関数をエクスポートすることで定義できます。
補足:
<title>
や<meta>
などの<head>
タグを手動でルートレイアウトに追加するべきではありません。代わりに、ストリーミングや<head>
要素の重複排除などの高度な要件を自動的に処理するMetadata APIを使用してください。
API リファレンスで利用可能なメタデータオプションの詳細を確認できます。
アクティブなナビゲーションリンク
usePathname()フックを使用して、ナビゲーションリンクがアクティブかどうかを判断できます。
usePathname()
はクライアントサイドのフックであるため、ナビゲーションリンクをクライアントコンポーネントに抽出する必要があります。これはレイアウトやテンプレートにインポートできます: