Layouts と Templates
特別なファイルであるlayout.jsとtemplate.jsを使用すると、ルート間で共有されるUIを作成できます。このページでは、これらの特別なファイルをどのように、そしていつ使用するかについて説明します。
Layouts
レイアウトは、複数のルート間で共有されるUIです。ナビゲーション時に、レイアウトは状態を保持し、インタラクティブなままで、再レンダリングされません。レイアウトはネストすることもできます。
layout.jsファイルからReactコンポーネントをデフォルトエクスポートすることで、レイアウトを定義できます。このコンポーネントは、レンダリング中に子レイアウト(存在する場合)またはページで埋められるchildren propを受け入れる必要があります。
たとえば、レイアウトは/dashboardおよび/dashboard/settingsページと共有されます:

- TypeScript
 - JavaScript
 
export default function DashboardLayout({
  children, // ページまたはネストされたレイアウトになります
}: {
  children: React.ReactNode
}) {
  return (
    <section>
      {/* ここに共有UIを含めます。例:ヘッダーやサイドバー */}
      <nav></nav>
      {children}
    </section>
  )
}
export default function DashboardLayout({
  children, // ページまたはネストされたレイアウトになります
}) {
  return (
    <section>
      {/* ここに共有UIを含めます。例:ヘッダーやサイドバー */}
      <nav></nav>
      {children}
    </section>
  )
}
Root Layout(必須)
root レイアウトはappディレクトリのトップレベルで定義され、すべてのルートに適用されます。このレイアウトは必須であり、htmlおよびbodyタグを含める必要があります。これにより、サーバーから返される初期HTMLを変更できます。
- TypeScript
 - JavaScript
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* レイアウトUI */}
        <main>{children}</main>
      </body>
    </html>
  )
}
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {/* レイアウトUI */}
        <main>{children}</main>
      </body>
    </html>
  )
}
ネストされたレイアウト
デフォルトでは、フォルダ階層内のレイアウトはネストされており、children propを介して子レイアウトをラップします。特定のルートセグメント(フォルダ)内にlayout.jsを追加することで、レイアウトをネストできます。
たとえば、/dashboardルート用のレイアウトを作成するには、dashboardフォルダ内に新しいlayout.jsファイルを追加します:

- TypeScript
 - JavaScript
 
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
  return <section>{children}</section>
}
上記の2つのレイアウトを組み合わせると、root レイアウト(app/layout.js)がダッシュボードレイアウト(app/dashboard/layout.js)をラップし、app/dashboard/*内のルートセグメントをラップします。
2つのレイアウトは次のようにネストされます:

Good to know:
- レイアウトには
 .js、.jsx、または.tsxファイル拡張子を使用できます。<html>および<body>タグを含めることができるのはroot レイアウトのみです。- 同じフォルダに
 layout.jsとpage.jsファイルが定義されている場合、レイアウトはページをラップします。- レイアウトはデフォルトでServer Componentsですが、Client Componentに設定することもできます。
 - レイアウトはデータを取得できます。詳細はデータ取得セクションを参照してください。
 - 親レイアウトとその子の間でデータを渡すことはできません。ただし、ルートで同じデータを複数回取得することができ、Reactはパフォーマンスに影響を与えることなくリクエストを自動的に重複排除します。
 - レイアウトは
 pathnameにアクセスできません(詳細はこちら)。ただし、インポートされたClient ComponentsはusePathnameフックを使用してpathnameにアクセスできます。- レイアウトは自分自身の下のルートセグメントにアクセスできません。すべてのルートセグメントにアクセスするには、Client Componentで
 useSelectedLayoutSegmentまたはuseSelectedLayoutSegmentsを使用できます。- Route Groupsを使用して、特定のルートセグメントを共有レイアウトに含めたり除外したりできます。
 - Route Groupsを使用して、複数のroot レイアウトを作成できます。こちらの例を参照してください。
 pagesディレクトリからの移行: root レイアウトは_app.jsおよび_document.jsファイルを置き換えます。移行ガイドを参照。
Templates
Templatesは、子レイアウトまたはページをラップする点でレイアウトに似ています。ルート間で持続し、状態を保持するレイアウトとは異なり、Templatesはナビゲーション時にその子の新しいインスタンスを作成します。つまり、ユーザーがTemplatesを共有するルート間をナビゲートすると、子の新しいインスタンスがマウントされ、DOM要素が再作成され、Client Componentsの状態は保持されず、エフェクトが再同期されます。
これらの特定の動作が必要な場合があり、Templatesはレイアウトよりも適したオプションとなるでしょう。たとえば:
- ナビゲーション時に
useEffectを再同期するため - ナビゲーション時に子Client Componentsの状態をリセットするため
 
Templateは、template.jsファイルからデフォルトのReactコンポーネントをエクスポートすることで定義できます。このコンポーネントはchildren propを受け入れる必要があります。

- TypeScript
 - JavaScript
 
export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}
export default function Template({ children }) {
  return <div>{children}</div>
}
ネストに関しては、template.jsはレイアウトとその子の間にレンダリングされます。以下は簡略化された出力です:
<Layout>
  {/* テンプレートにはユニークなキーが与えられます。 */}
  <Template key={routeParam}>{children}</Template>
</Layout>
例
メタデータ
Metadata APIを使用して、titleやmetaなどの<head> HTML要素を変更できます。
メタデータは、layout.jsまたはpage.jsファイルでmetadataオブジェクトまたはgenerateMetadata関数をエクスポートすることで定義できます。
- TypeScript
 - JavaScript
 
import type { Metadata } from 'next'
export const metadata: Metadata = {
  title: 'Next.js',
}
export default function Page() {
  return '...'
}
export const metadata = {
  title: 'Next.js',
}
export default function Page() {
  return '...'
}
Good to know: root レイアウトに
<title>や<meta>などの<head>タグを手動で追加するべきではありません。代わりに、Metadata APIを使用してください。これにより、ストリーミングや<head>要素の重複排除などの高度な要件が自動的に処理されます。
利用可能なメタデータオプションについては、APIリファレンスで詳細を確認してください。
アクティブなナビゲーションリンク
usePathname()フックを使用して、ナビゲーションリンクがアクティブかどうかを判断できます。
usePathname()はクライアントフックであるため、ナビゲーションリンクをClient Componentに抽出し、レイアウトまたはテンプレートにインポートする必要があります:
- TypeScript
 - JavaScript
 
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function NavLinks() {
  const pathname = usePathname()
  return (
    <nav>
      <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
        Home
      </Link>
      <Link
        className={`link ${pathname === '/about' ? 'active' : ''}`}
        href="/about"
      >
        About
      </Link>
    </nav>
  )
}
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function Links() {
  const pathname = usePathname()
  return (
    <nav>
      <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
        Home
      </Link>
      <Link
        className={`link ${pathname === '/about' ? 'active' : ''}`}
        href="/about"
      >
        About
      </Link>
    </nav>
  )
}
- TypeScript
 - JavaScript
 
import { NavLinks } from '@/app/ui/nav-links'
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <NavLinks />
        <main>{children}</main>
      </body>
    </html>
  )
}
import { NavLinks } from '@/app/ui/nav-links'
export default function Layout({ children }) {
  return (
    <html lang="en">
      <body>
        <NavLinks />
        <main>{children}</main>
      </body>
    </html>
  )
}