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 のコンポーネントが含まれますが、LoadingError などの特別なファイルが含まれる場合もあります。

params (オプション)

ルートセグメントからそのレイアウトまでの 動的ルートパラメータ (dynamic route parameters) オブジェクトです。

URLparams
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/analyticspage.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.0layout が導入されました。