跳到主要內容

layout.js

layout 檔案用於在你的 Next.js 應用程式中定義版面配置。

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

根版面配置 是根目錄 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 將會被版面配置所包裝的路由區段填入。這些主要會是子層 版面配置(如果存在)或 頁面 的元件,但也可能是其他特殊檔案,例如 載入中錯誤(在適用的情況下)。

params (選填)

一個 Promise,解析為一個物件,其中包含從根區段到該版面配置的 動態路由參數 物件。

app/dashboard/[team]/layout.tsx
export default async function Layout({
  params,
}: {
  params: Promise<{ team: string }>
}) {
  const team = (await params).team
}
路由範例網址params
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 是一個 promise。你必須使用 async/await 或 React 的 use 函式來存取這些值。
    • 在版本 14 及更早版本中,params 是一個同步 prop。為了協助向後相容性,你仍然可以在 Next.js 15 中同步存取它,但此行為在未來將會被棄用。

根版面配置

app 目錄必須包含一個根目錄 app/layout.js

app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>{children}</body>
    </html>
  )
}
  • 根版面配置必須定義 <html><body> 標籤。
    • 不應手動將 <head> 標籤(例如 <title><meta>)新增至根版面配置。相反地,你應該使用 Metadata API,它會自動處理進階需求,例如串流和重複資料刪除 <head> 元素。
  • 你可以使用 路由群組 來建立多個根版面配置。
    • 多個根版面配置之間導航將會導致完整頁面載入(而不是用戶端導航)。例如,從使用 app/(shop)/layout.js/cart 導航到使用 app/(marketing)/layout.js/blog 將會導致完整頁面載入。這適用於多個根版面配置。

注意事項

版面配置不接收 searchParams

頁面 不同,版面配置元件接收 searchParams prop。這是因為共用版面配置在 導航期間不會重新渲染,這可能會導致導航之間 searchParams 過時。

當使用用戶端導航時,Next.js 會自動僅渲染兩個路由之間共用版面配置下方的頁面部分。

例如,在以下目錄結構中,dashboard/layout.tsx/dashboard/settings/dashboard/analytics 的共用版面配置

File structure showing a dashboard folder nesting a layout.tsx file, and settings and analytics folders with their own pages

當從 /dashboard/settings 導航到 /dashboard/analytics 時,/dashboard/analytics 中的 page.tsx 將會在伺服器上重新渲染,而 dashboard/layout.tsx不會重新渲染,因為它是兩個路由之間共用的 UI。

這種效能最佳化允許共享版面配置的頁面之間的導航速度更快,因為只需要執行頁面的資料抓取和渲染,而不是可能包含抓取自身資料的共用版面配置的整個路由。

由於 dashboard/layout.tsx 不會重新渲染,因此版面配置伺服器元件中的 searchParams prop 在導航後可能會變得過時

相反地,在版面配置中使用頁面 searchParams prop 或用戶端元件中的 useSearchParams hook,它們會在用戶端使用最新的 searchParams 重新渲染。

版面配置無法存取 pathname

版面配置無法存取 pathname。這是因為版面配置預設為伺服器元件,且 在用戶端導航期間不會重新渲染,這可能會導致導航之間 pathname 過時。為了防止過時,Next.js 需要重新抓取路由的所有區段,從而失去快取的優勢並增加導航時的 RSC payload 大小。

相反地,你可以將依賴 pathname 的邏輯提取到用戶端元件中,並將其匯入到你的版面配置中。由於用戶端元件在導航期間會重新渲染(但不會重新抓取),因此你可以使用 Next.js hook,例如 usePathname 來存取目前的 pathname 並防止過時。

app/dashboard/layout.tsx
import { ClientComponent } from '@/app/ui/ClientComponent'
 
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <>
      <ClientComponent />
      {/* Other Layout 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>
  )
}

在用戶端元件中讀取 params

若要在用戶端元件中使用 params(不能是 async),你可以使用 React 的 use 函式來讀取 promise

app/page.tsx
'use client'
 
import { use } from 'react'
 
export default function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = use(params)
}

版本歷史

版本變更
v15.0.0-RCparams 現在是一個 promise。有一個 codemod 可用。
v13.0.0引入 layout