layout.js
layout
ファイルは、Next.jsアプリケーション内でレイアウトを定義するために使用されます。
- TypeScript
- JavaScript
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
root レイアウトは、root app
ディレクトリ内の最上位のレイアウトです。これは、<html>
や<body>
タグ、その他グローバルに共有されるUIを定義するために使用されます。
- TypeScript
- JavaScript
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
propを受け入れ、使用する必要があります。レンダリング中に、children
はレイアウトがラップするルートセグメントで埋められます。これらは主に子Layout(存在する場合)やPageのコンポーネントですが、適用される場合には他の特別なファイル、例えばLoadingやErrorである可能性もあります。
params
(オプション)
rootセグメントからそのレイアウトに至るまでの動的ルートパラメータオブジェクトを含むオブジェクトに解決されるプロミスです。
- TypeScript
- JavaScript
export default async function Layout({
params,
}: {
params: Promise<{ team: string }>
}) {
const team = (await params).team
}
export default async function Layout({ params }) {
const team = (await params).team
}
例のルート | URL | params |
---|---|---|
app/dashboard/[team]/layout.js | /dashboard/1 | Promise<{ team: '1' }> |
app/shop/[tag]/[item]/layout.js | /shop/1/2 | Promise<{ tag: '1', item: '2' }> |
app/blog/[...slug]/layout.js | /blog/1/2 | Promise<{ slug: ['1', '2'] }> |
params
propはプロミスであるため。値にアクセスするためにはasync/await
またはReactのuse
関数を使用する必要があります。- バージョン14以前では、
params
は同期的なpropでした。互換性を保つために、Next.js 15では同期的にアクセスすることが可能ですが、この動作は将来廃止される予定です。
- バージョン14以前では、
Root レイアウト
app
ディレクトリには、root app/layout.js
を含める必要があります。
- TypeScript
- JavaScript
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>{children}</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html>
<body>{children}</body>
</html>
)
}
- Root レイアウトには、
<html>
タグと<body>
タグを定義する必要があります。- root レイアウトに
<title>
や<meta>
のような<head>
タグを手動で追加するべきではありません。代わりに、メタデータAPIを利用するべきで、これによりストリーミングや<head>
要素の重複除去といった高度な要件が自動で処理されます。
- root レイアウトに
- ルートグループ(route groups)を使用して、複数のroot レイアウトを作成できます。
- 複数のrootレイアウト間での移動は、クライアントサイドのナビゲーションとは対照的に、フルページロードが発生します。例えば、
/cart
からapp/(shop)/layout.js
を使い、/blog
に移動してapp/(marketing)/layout.js
を使うと、フルページロードが発生します。これは複数のrootレイアウトにのみ適用されます。
- 複数のrootレイアウト間での移動は、クライアントサイドのナビゲーションとは対照的に、フルページロードが発生します。例えば、
注意事項
レイアウトはsearchParams
を受け取りません
Pagesとは異なり、レイアウトコンポーネントはsearchParams
propを受け取りません。これは、共通のレイアウトがナビゲーション中に再レンダリングされないため、ナビゲーション間で古くなったsearchParams
が表示される可能性があるためです。
クライアントサイドのナビゲーションを使用する場合、Next.jsは2つのルート間の共通レイアウトの下にあるページの部分だけをレンダリングします。
例えば、次のディレクトリ構造では、dashboard/layout.tsx
は/dashboard/settings
と/dashboard/analytics
の両方の共通レイアウトです:
/dashboard/settings
から/dashboard/analytics
にナビゲートすると、dashboard/analytics
のpage.tsx
はサーバー上で再レンダリングされますが、共通のUIであるdashboard/layout.tsx
は再レンダリングされません。
このパフォーマンス最適化は、共通のレイアウトを共有するページ間のナビゲーションを高速化し、ページのデータフェッチとレンダリングだけを実行することで、独自のデータをフェッチする可能性のある共有レイアウトを含む全ルートを実行することを避けます。
このため、ナビゲーション後にレイアウトServer Component内のsearchParams
propが古くなる可能性があります。
代わりに、PageコンポーネントでsearchParams
propまたは、レイアウト内のClient ComponentでuseSearchParams
フックを使用します。これらはナビゲーション中に最新のsearchParams
でクライアントで再レンダリングされます。
レイアウトはpathname
にアクセスできません
レイアウトはpathname
にアクセスできません。これは、レイアウトがデフォルトでServer Componentsであり、クライアントサイドのナビゲーション中に再レンダリングされないため、ナビゲーションの間でpathname
が古くなる可能性があるためです。古くなるのを防ぐためには、Next.jsはルートのすべてのセグメントをフェッチし直す必要があり、キャッシングの利点を失い、ナビゲーション時のRSCペイロードサイズが増加します。
代わりに、パス名に依存するロジックをClient Componentに抽出し、レイアウトにインポートすることができます。クライアントコンポーネントはナビゲーション中に再レンダリングされますが、フェッチされることはないため、Next.jsのフック、例えばusePathname
を使用して現在のパス名にアクセスし、古くなるのを防ぐことができます。
- TypeScript
- JavaScript
import { ClientComponent } from '@/app/ui/ClientComponent'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<ClientComponent />
{/* 他のレイアウトUI */}
<main>{children}</main>
</>
)
}
import { ClientComponent } from '@/app/ui/ClientComponent'
export default function Layout({ children }) {
return (
<>
<ClientComponent />
{/* 他のレイアウトUI */}
<main>{children}</main>
</>
)
}
一般的なpathname
パターンはparams
propで実装することも可能です
詳細は例セクションを参照してください。
例
params
に基づくコンテンツの表示
動的ルートセグメントを使用して、params
propに基づいて特定のコンテンツを表示またはフェッチすることができます。
- TypeScript
- JavaScript
export default async function DashboardLayout({
children,
params,
}: {
children: React.ReactNode
params: Promise<{ team: string }>
}) {
const { team } = await params
return (
<section>
<header>
<h1>Welcome to {team}'s Dashboard</h1>
</header>
<main>{children}</main>
</section>
)
}
export default async function DashboardLayout({ children, params }) {
const { team } = await params
return (
<section>
<header>
<h1>Welcome to {team}'s Dashboard</h1>
</header>
<main>{children}</main>
</section>
)
}
Client Componentsでのparams
の読み取り
Client Component(async
にできない)でparams
を使用するために、Reactのuse
関数を使用してプロミスを読み取ることができます:
- TypeScript
- JavaScript
'use client'
import { use } from 'react'
export function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = use(params)
}
'use client'
import { use } from 'react'
export function Page({ params }) {
const { slug } = use(params)
}
バージョン履歴
バージョン | 変更点 |
---|---|
v15.0.0-RC | params はプロミスになりました。codemodが利用可能です。 |
v13.0.0 | layout が導入されました。 |