template.js
テンプレートファイルは、レイアウトに似ていますが、レイアウトまたはページをラップします。ルートをまたいで永続し状態を維持するレイアウトとは異なり、テンプレートには一意のキーが与えられます。これは、子クライアントコンポーネントがナビゲーション時に状態をリセットすることを意味します。
これらは、次のような場合に役立ちます。
- ナビゲーション時に
useEffectを再同期する。 - ナビゲーション時に子クライアントコンポーネントの状態をリセットする。例えば、入力フィールド。
- デフォルトのフレームワークの動作を変更する。例えば、レイアウト内の Suspense の境界は最初のロード時にのみフォールバックを表示しますが、テンプレートはすべてのナビゲーションで表示します。
規約
テンプレートは、template.js ファイルからデフォルトの React コンポーネントをエクスポートすることで定義できます。コンポーネントは children プロップを受け取る必要があります。

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.0 | template が導入されました。 |
役に立ちましたか?
