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
| Layout | Template | |
|---|---|---|
| Перемонтирование | Нет | Да, при каждой навигации |
| Состояние (useState) | Сохраняется | Сбрасывается |
| useEffect | Не перезапускается | Запускается заново |
| DOM | Не пересоздается | Пересоздается |
Специальные файлы в сегменте
Layout оборачивает остальные специальные файлы в определенном порядке:
layout.tsx
template.tsx
error.tsx (React Error Boundary)
loading.tsx (React Suspense)
not-found.tsx
page.tsx
Практический совет:
В большинстве случаев используй layout. Template нужен только когда требуется сбрасывать состояние или запускать эффекты при навигации.
Полезные ресурсы
- nextjs.org/docs — Layouts and Templates
- layout.tsx API Reference