layout.js

Макет (layout) — это пользовательский интерфейс, общий для нескольких маршрутов.

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>, а также других элементов интерфейса, общих для всего приложения.

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>
  )
}

Пропсы

children (обязательный)

Компоненты макета должны принимать и использовать пропс children. Во время рендеринга children будет заполнен сегментами маршрута, которые оборачивает макет. В основном это будет компонент дочернего Макета (если он существует) или Страницы, но также могут быть и другие специальные файлы, такие как Загрузка (Loading) или Ошибка (Error), когда это применимо.

params (опциональный)

Объект динамических параметров маршрута от корневого сегмента до данного макета.

Пример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

В отличие от Страниц (Pages), компоненты макета не получают пропс searchParams. Это связано с тем, что общий макет не перерендеривается при навигации, что может привести к устаревшим searchParams между переходами.

При использовании клиентской навигации Next.js автоматически рендерит только ту часть страницы, которая находится ниже общего макета между двумя маршрутами.

Например, в следующей структуре директорий dashboard/layout.tsx является общим макетом для /dashboard/settings и /dashboard/analytics:

app
└── dashboard
    ├── layout.tsx
    ├── settings
    │   └── page.tsx
    └── analytics
        └── page.js

При переходе с /dashboard/settings на /dashboard/analytics будет выполнен рендеринг page.tsx в /dashboard/analytics на сервере, так как это изменившийся интерфейс, в то время как dashboard/layout.tsx не будет перерендерен, так как это общий интерфейс для обоих маршрутов.

Эта оптимизация производительности позволяет ускорить навигацию между страницами с общим макетом, так как выполняется только получение данных и рендеринг страницы, а не всего маршрута, который может включать общие макеты с собственными запросами данных.

Поскольку dashboard/layout.tsx не перерендеривается, пропс searchParams в серверном компоненте макета может устареть после навигации.

  • Вместо этого используйте пропс searchParams Страницы или хук useSearchParams в клиентском компоненте, который перерендеривается на клиенте с актуальными searchParams.

Корневые макеты

  • В директории app обязательно должен быть корневой app/layout.js.
  • Корневой макет обязательно должен определять теги <html> и <body>.
    • Вручную добавлять теги <head>, такие как <title> и <meta>, в корневые макеты не следует. Вместо этого используйте Metadata API, который автоматически обрабатывает сложные требования, такие как потоковая передача и дедупликация элементов <head>.
  • Вы можете использовать группы маршрутов (route groups) для создания нескольких корневых макетов.
    • Навигация между несколькими корневыми макетами вызовет полную перезагрузку страницы (в отличие от клиентской навигации). Например, переход с /cart, использующего app/(shop)/layout.js, на /blog, использующий app/(marketing)/layout.js, вызовет полную перезагрузку страницы. Это применяется только к нескольким корневым макетам.

История версий

ВерсияИзменения
v13.0.0Добавлен layout.