メインコンテンツまでスキップ

layout.js

layoutファイルは、Next.jsアプリケーション内でレイアウトを定義するために使用されます。

app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}

root レイアウトは、root appディレクトリ内の最上位のレイアウトです。これは、<html><body>タグ、その他グローバルに共有されるUIを定義するために使用されます。

app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}

リファレンス

Props

children (必須)

レイアウトコンポーネントは、children propを受け入れ、使用する必要があります。レンダリング中に、childrenはレイアウトがラップするルートセグメントで埋められます。これらは主に子Layout(存在する場合)やPageのコンポーネントですが、適用される場合には他の特別なファイル、例えばLoadingErrorである可能性もあります。

params (オプション)

rootセグメントからそのレイアウトに至るまでの動的ルートパラメータオブジェクトを含むオブジェクトに解決されるプロミスです。

app/dashboard/[team]/layout.tsx
export default async function Layout({
params,
}: {
params: Promise<{ team: string }>
}) {
const team = (await params).team
}
例のルートURLparams
app/dashboard/[team]/layout.js/dashboard/1Promise<{ team: '1' }>
app/shop/[tag]/[item]/layout.js/shop/1/2Promise<{ tag: '1', item: '2' }>
app/blog/[...slug]/layout.js/blog/1/2Promise<{ slug: ['1', '2'] }>
  • params propはプロミスであるため。値にアクセスするためにはasync/awaitまたはReactのuse関数を使用する必要があります。
    • バージョン14以前では、paramsは同期的なpropでした。互換性を保つために、Next.js 15では同期的にアクセスすることが可能ですが、この動作は将来廃止される予定です。

Root レイアウト

appディレクトリには、root app/layout.jsを含める必要があります

app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>{children}</body>
</html>
)
}
  • Root レイアウトには、<html>タグと<body>タグを定義する必要があります。
    • root レイアウトに<title><meta>のような<head>タグを手動で追加するべきではありません。代わりに、メタデータAPIを利用するべきで、これによりストリーミングや<head>要素の重複除去といった高度な要件が自動で処理されます。
  • ルートグループ(route groups)を使用して、複数のroot レイアウトを作成できます。
    • 複数のrootレイアウト間での移動は、クライアントサイドのナビゲーションとは対照的に、フルページロードが発生します。例えば、/cartからapp/(shop)/layout.jsを使い、/blogに移動してapp/(marketing)/layout.jsを使うと、フルページロードが発生します。これは複数のrootレイアウトにのみ適用されます。

注意事項

レイアウトはsearchParamsを受け取りません

Pagesとは異なり、レイアウトコンポーネントはsearchParams propを受け取りません。これは、共通のレイアウトがナビゲーション中に再レンダリングされないため、ナビゲーション間で古くなったsearchParamsが表示される可能性があるためです。

クライアントサイドのナビゲーションを使用する場合、Next.jsは2つのルート間の共通レイアウトの下にあるページの部分だけをレンダリングします。

例えば、次のディレクトリ構造では、dashboard/layout.tsx/dashboard/settings/dashboard/analyticsの両方の共通レイアウトです:

dashboardフォルダがlayout.tsxファイルをネストし、settingsとanalyticsフォルダがそれぞれ独自のページを持つファイル構造dashboardフォルダがlayout.tsxファイルをネストし、settingsとanalyticsフォルダがそれぞれ独自のページを持つファイル構造

/dashboard/settingsから/dashboard/analyticsにナビゲートすると、dashboard/analyticspage.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を使用して現在のパス名にアクセスし、古くなるのを防ぐことができます。

app/dashboard/layout.tsx
import { ClientComponent } from '@/app/ui/ClientComponent'

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<ClientComponent />
{/* 他のレイアウトUI */}
<main>{children}</main>
</>
)
}

一般的なpathnameパターンはparams propで実装することも可能です

詳細はセクションを参照してください。

paramsに基づくコンテンツの表示

動的ルートセグメントを使用して、params propに基づいて特定のコンテンツを表示またはフェッチすることができます。

app/dashboard/layout.tsx
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>
)
}

Client Componentsでのparamsの読み取り

Client Component(asyncにできない)でparamsを使用するために、Reactのuse関数を使用してプロミスを読み取ることができます:

app/page.tsx
'use client'

import { use } from 'react'

export function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = use(params)
}

バージョン履歴

バージョン変更点
v15.0.0-RCparamsはプロミスになりました。codemodが利用可能です。
v13.0.0layoutが導入されました。