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>
タグを手動で追加するべきではありません。代わりに、Metadata API を使用するべきです。これは、ストリーミングや<head>
要素の重複排除などの高度な要件を自動的に処理します
- root レイアウトに
- route groupを使用して、複数の 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
へとナビゲートする際、page.tsx
は /dashboard/analytics
上でサーバーで再描画されますが、dashboard/layout.tsx
は共通のUIであるため再描画されません。
このパフォーマンスの最適化により、レイアウトを共有するページ間のナビゲーションが高速化され、代わりにページのデータ取得およびレンダリングのみが実行されることになり、共通レイアウトが独自のデータを取得することがあるフルルートを含む全体の実行が省略されます。
dashboard/layout.tsx
が再レンダリングされないため、レイアウトのサーバーコンポーネント内の searchParams
prop は、ナビゲーション後に古くなるかもしれません。
代わりに、ページの searchParams
prop またはレイアウト内のクライアントコンポーネントでのuseSearchParams
フックを使用してください。これらは最新の searchParams
でクライアントで再レンダリングされます。
レイアウトは pathname
にアクセスできない
レイアウトは pathname
にアクセスできません。これは、レイアウトがデフォルトでサーバーコンポーネントであり、クライアントサイドナビゲーション中に再レンダリングされないためです。これにより、ナビゲーション間でpathname
が古くなる可能性があります。古くならないようにするためには、Next.js はルートのすべてのセグメントを再取得する必要があり、キャッシュの利点を失ってRSC ペイロードサイズがナビゲーション時に増加することになります。
代わりに、pathname
に依存するロジックをクライアントコンポーネントに抽出し、それをレイアウトにインポートすることができます。クライアントコンポーネントはナビゲーション時に再レンダリングされる(ただし再取得されるわけではない)ため、Next.jsのusePathname
などのフックを使用して、現在の pathname
にアクセスし、古くならないようにすることができます。
- 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 で実装できます。
詳細は examples セクションをご覧ください。
例
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>
)
}
クライアントコンポーネントでの params
の読み取り
クライアントコンポーネント(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 が導入されました; |