コンテンツにスキップ

template.js

テンプレートファイルは、レイアウトに似ていますが、レイアウトまたはページをラップします。ルートをまたいで永続し状態を維持するレイアウトとは異なり、テンプレートには一意のキーが与えられます。これは、子クライアントコンポーネントがナビゲーション時に状態をリセットすることを意味します。

これらは、次のような場合に役立ちます。

  • ナビゲーション時に useEffect を再同期する。
  • ナビゲーション時に子クライアントコンポーネントの状態をリセットする。例えば、入力フィールド。
  • デフォルトのフレームワークの動作を変更する。例えば、レイアウト内の Suspense の境界は最初のロード時にのみフォールバックを表示しますが、テンプレートはすべてのナビゲーションで表示します。

規約

テンプレートは、template.js ファイルからデフォルトの React コンポーネントをエクスポートすることで定義できます。コンポーネントは children プロップを受け取る必要があります。

template.js special file
app/template.tsx
export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}

ネストの観点から、template.js はレイアウトとその子要素の間にレンダリングされます。以下に簡略化された出力を示します。

出力
<Layout>
  {/* Note that the template is given a unique key. */}
  <Template key={routeParam}>{children}</Template>
</Layout>

Props

children (必須)

テンプレートは children プロップを受け取ります。

出力
<Layout>
  {/* Note that the template is automatically given a unique key. */}
  <Template key={routeParam}>{children}</Template>
</Layout>

動作

  • サーバーコンポーネント: デフォルトでは、テンプレートはサーバーコンポーネントです。
  • ナビゲーション時: テンプレートには、セグメントレベルごとに一意のキーが与えられます。セグメント(動的パラメータを含む)が変更されると、テンプレートは再マウントされます。より深いセグメント内のナビゲーションでは、上位レベルのテンプレートは再マウントされません。検索パラメータは再マウントをトリガーしません。
  • 状態のリセット: テンプレート内のクライアントコンポーネントは、ナビゲーション時に状態がリセットされます。
  • エフェクトの再実行: useEffect のようなエフェクトは、コンポーネントが再マウントされると再同期されます。
  • DOM のリセット: テンプレート内の DOM 要素は完全に再作成されます。

ナビゲーション中および再マウント時のテンプレート

このセクションでは、ナビゲーション中のテンプレートの動作を説明します。各ルート変更時にどのテンプレートが再マウントされ、その理由を段階的に示します。

このプロジェクトツリーを使用する

app
├── about
│   ├── page.tsx
├── blog
│   ├── [slug]
│   │   └── page.tsx
│   ├── page.tsx
│   └── template.tsx
├── layout.tsx
├── page.tsx
└── template.tsx

/ から開始すると、React ツリーはおおよそ次のようになります。

注: 例に示されている key 値は例示的なものです。アプリケーションの値は異なる場合があります。

出力
<RootLayout>
  {/* app/template.tsx */}
  <Template key="/">
    <Page />
  </Template>
</RootLayout>

/about にナビゲートすると(最初のセグメントが変更)、ルートテンプレートのキーが変更され、再マウントされます。

出力
<RootLayout>
  {/* app/template.tsx */}
  <Template key="/about">
    <AboutPage />
  </Template>
</RootLayout>

/blog にナビゲートすると(最初のセグメントが変更)、ルートテンプレートのキーが変更され、再マウントされ、blog レベルのテンプレートがマウントされます。

出力
<RootLayout>
  {/* app/template.tsx (root) */}
  <Template key="/blog">
    {/* app/blog/template.tsx */}
    <Template key="/blog">
      <BlogIndexPage />
    </Template>
  </Template>
</RootLayout>

同じ最初のセグメント内で /blog/first-post にナビゲートすると(子セグメントが変更)、ルートテンプレートのキーは変更されませんが、blog レベルのテンプレートのキーが変更され、再マウントされます。

出力
<RootLayout>
  {/* app/template.tsx (root) */}
  <Template key="/blog">
    {/* app/blog/template.tsx */}
    {/* remounts because the child segment at this level changed */}
    <Template key="/blog/first-post">
      <BlogPostPage slug="first-post" />
    </Template>
  </Template>
</RootLayout>

/blog/second-post にナビゲートすると(同じ最初のセグメント、異なる子セグメント)、ルートテンプレートのキーは変更されませんが、blog レベルのテンプレートのキーが変更され、再度再マウントされます。

出力
<RootLayout>
  {/* app/template.tsx (root) */}
  <Template key="/blog">
    {/* app/blog/template.tsx */}
    {/* remounts again due to changed child segment */}
    <Template key="/blog/second-post">
      <BlogPostPage slug="second-post" />
    </Template>
  </Template>
</RootLayout>

バージョン履歴

バージョン変更履歴
v13.0.0template が導入されました。