layout.js
レイアウト (layout) とは、複数のルート間で共有される UI のことです。
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
ルートレイアウト (root layout) は、ルート app
ディレクトリの最上位レイアウトです。<html>
タグや <body>
タグ、その他のグローバルに共有される UI を定義するために使用されます。
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Props
children
(必須)
レイアウトコンポーネントは children
プロップを受け取り、使用する必要があります。レンダリング時には、children
にはレイアウトがラップしているルートセグメントが含まれます。これには主に子の Layout(存在する場合)または Page のコンポーネントが含まれますが、Loading や Error などの特別なファイルが含まれる場合もあります。
params
(オプション)
ルートセグメントからそのレイアウトまでの 動的ルートパラメータ (dynamic route parameters) オブジェクトです。
例 | URL | params |
---|---|---|
app/dashboard/[team]/layout.js | /dashboard/1 | { team: '1' } |
app/shop/[tag]/[item]/layout.js | /shop/1/2 | { tag: '1', item: '2' } |
app/blog/[...slug]/layout.js | /blog/1/2 | { slug: ['1', '2'] } |
例:
export default function ShopLayout({
children,
params,
}: {
children: React.ReactNode
params: {
tag: string
item: string
}
}) {
// URL -> /shop/shoes/nike-air-max-97
// `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
return <section>{children}</section>
}
export default function ShopLayout({ children, params }) {
// URL -> /shop/shoes/nike-air-max-97
// `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
return <section>{children}</section>
}
知っておくと良いこと
レイアウトは searchParams
を受け取らない
Page とは異なり、レイアウトコンポーネントは searchParams
プロップを受け取りません。これは、共有レイアウトが ナビゲーション中に再レンダリングされないため、ナビゲーション間で searchParams
が古くなる可能性があるためです。
クライアントサイドナビゲーションを使用する場合、Next.js は自動的に2つのルート間で共通のレイアウトの下のページ部分のみをレンダリングします。
例えば、以下のディレクトリ構造では、dashboard/layout.tsx
は /dashboard/settings
と /dashboard/analytics
の両方の共通レイアウトです:
app
└── dashboard
├── layout.tsx
├── settings
│ └── page.tsx
└── analytics
└── page.js
/dashboard/settings
から /dashboard/analytics
にナビゲートする場合、/dashboard/analytics
の page.tsx
は変更された UI であるためサーバーでレンダリングされますが、dashboard/layout.tsx
は2つのルート間で共通の UI であるため、再レンダリングされません。
このパフォーマンス最適化により、レイアウトを共有するページ間のナビゲーションが高速化されます。ページのデータ取得とレンダリングのみが実行され、独自のデータを取得する可能性のある共有レイアウトを含むルート全体が実行されることはありません。
dashboard/layout.tsx
が再レンダリングされないため、レイアウトのサーバーコンポーネント内の searchParams
プロップはナビゲーション後に古くなる可能性があります。
- 代わりに、Page の
searchParams
プロップを使用するか、クライアントコンポーネント内でuseSearchParams
フックを使用してください。これらは最新のsearchParams
でクライアント側で再レンダリングされます。
ルートレイアウト
app
ディレクトリには、必ずルートapp/layout.js
が含まれている必要があります。- ルートレイアウトには、必ず
<html>
タグと<body>
タグを定義する必要があります。<title>
や<meta>
などの<head>
タグをルートレイアウトに手動で追加するべきではありません。代わりに、Metadata API を使用してください。この API は、ストリーミングや<head>
要素の重複排除などの高度な要件を自動的に処理します。
- route groups (ルートグループ) を使用して、複数のルートレイアウトを作成できます。
- 複数のルートレイアウト間をナビゲートすると、ページ全体の再読み込みが発生します(クライアントサイドナビゲーションとは異なります)。例えば、
app/(shop)/layout.js
を使用する/cart
からapp/(marketing)/layout.js
を使用する/blog
にナビゲートすると、ページ全体が再読み込みされます。これは複数のルートレイアウトにのみ適用されます。
- 複数のルートレイアウト間をナビゲートすると、ページ全体の再読み込みが発生します(クライアントサイドナビゲーションとは異なります)。例えば、
バージョン履歴
バージョン | 変更内容 |
---|---|
v13.0.0 | layout が導入されました。 |