Layouts и Templates в Next.js

В Next.js App Router layouts и templates определяют общую структуру страниц. Layout оборачивает дочерние страницы и сохраняет свое состояние при навигации. Template делает то же самое, но пересоздается при каждом переходе.

Layouts

Layout это компонент, который разделяется между несколькими страницами. При навигации между дочерними страницами layout не перемонтируется и сохраняет состояние:

// app/layout.tsx (корневой layout)
export default function RootLayout({
  children
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <Header />
        <main>{children}</main>
        <Footer />
      </body>
    </html>
  )
}

Корневой layout обязателен и должен содержать теги <html> и <body>.

Вложенные layouts

Layouts могут быть вложенными. Каждый сегмент может иметь свой layout:

// app/docs/layout.tsx
export default function DocsLayout({
  children
}: {
  children: React.ReactNode
}) {
  return (
    <div className="flex">
      <DocsSidebar />
      <div className="flex-1">{children}</div>
    </div>
  )
}

Когда пользователь переходит между страницами документации на Hack Frontend, боковая навигация (sidebar) не перемонтируется. Это дает плавный UX.

Сохранение состояния

Ключевое свойство layout: при навигации между дочерними страницами React не перемонтирует layout. Это значит:

  • Состояние useState сохраняется
  • Эффекты useEffect не перезапускаются
  • DOM не пересоздается
'use client'

// app/problems/layout.tsx
import { useState } from 'react'

export default function ProblemsLayout({
  children
}: {
  children: React.ReactNode
}) {
  const [filter, setFilter] = useState('all')

  return (
    <div>
      <FilterBar value={filter} onChange={setFilter} />
      {children}
    </div>
  )
}

Фильтр сохранится при навигации между /problems/1 и /problems/2.

Templates

Template работает как layout, но пересоздается при каждой навигации:

// app/docs/template.tsx
export default function DocsTemplate({
  children
}: {
  children: React.ReactNode
}) {
  return <div>{children}</div>
}

Когда использовать template вместо layout

  • Анимации входа/выхода при навигации
  • Логирование просмотров страниц (useEffect сработает при каждом переходе)
  • Сброс состояния формы при переходе между страницами

Layout vs Template

LayoutTemplate
ПеремонтированиеНетДа, при каждой навигации
Состояние (useState)СохраняетсяСбрасывается
useEffectНе перезапускаетсяЗапускается заново
DOMНе пересоздаетсяПересоздается

Специальные файлы в сегменте

Layout оборачивает остальные специальные файлы в определенном порядке:

layout.tsx
  template.tsx
    error.tsx (React Error Boundary)
      loading.tsx (React Suspense)
        not-found.tsx
          page.tsx

Практический совет:

В большинстве случаев используй layout. Template нужен только когда требуется сбрасывать состояние или запускать эффекты при навигации.

Полезные ресурсы

Связанные темы