7 - Кастомная страница not-found. Вложенные layout и template страницы в Next.js

Для доступа к видео войдите в систему

7 - Кастомная страница not-found. Вложенные layout и template страницы в Next.js

Оценить качество материала и подачу материала автором видео:

Front-end

Трудоустройтесь middle front-end разработчиком на React JS (TypeScript) за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Front-end

Back-end

Трудоустройтесь middle back-end разработчиком за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Back-end

Карьерный бустер

Получите коммерческий опыт на реальных стартапах, прокачайте tech & soft навыки, научитесь работать в команде, проходить собеседования и получите первую работу в IT!

Перейти на курс
Карьерный бустер

Основы Front-end

Сделайте первый шаг в IT, освоив базовые знания разработки и научившись создавать небольшие проекты на JavaScript

Перейти на курс
Основы Front-end

Основы Back-end

Сделайте первый шаг в IT, освоив базовые знания разработки. Без опыта. Без математики. Только практика: JavaScript, SQL, Node JS, база данных

Перейти на курс
Основы Back-end

Кастомная страница not-found. Вложенные layout и template страницы в Next.js

Автор конспекта: Стогниева Виктория

1. Создание кастомной страницы 404 (Not-Found)

1.1. Стратегическая важность страницы ошибки

Стандартная страница 404 от Next.js функциональна, но в профессиональной разработке она является признаком незавершенного продукта. Кастомная страница ошибки — это не просто вежливость, а стратегический инструмент для:

  • Сохранения стилистики вашего сайта
  • Удержания посетителя
  • Мягкого направления пользователя обратно в рабочую часть приложения

1.2. Поведение по умолчанию и реализация

По умолчанию Next.js отображает стандартную страницу 404. Для создания собственной:

  1. Расположение файла: Создайте в корневой директории app/
  2. Зарезервированное имя: Файл должен называться not-found.tsx (или .js)
  3. Структура компонента: Обычный React-компонент с экспортом по умололчанию

Пример реализации:

not-found.tsx
export default function NotFound() {
  return (
    <div>
      <div>Not Found</div>
      <Link href="/">Go to main</Link>
    </div>
  )
}

1.3. Результат и применение

После создания файла not-found.tsx при переходе по любому несуществующему URL пользователь будет видеть вашу кастомную страницу 404. Это простой, но эффективный способ улучшить взаимодействие с пользователем и придать приложению завершенный вид.

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

2. Вложенные Layouts для общей структуры и логики

2.1. Концепция иерархической структуры

Файлы Layout в Next.js — это мощный инструмент для создания общих и переиспользуемых компонентов интерфейса, которые оборачивают целые группы страниц. Это позволяет избежать дублирования кода, такого как хедеры, футеры или боковые панели, и выносить общую логику (например, запросы данных) на один уровень выше.

Существует два типа Layouts: корневой и вложенный.

Сравнительная таблица Layouts:

КритерийКорневой Layout (app/layout.tsx)Вложенный Layout (app/profile/layout.tsx)
Обязательные тегиДолжен содержать <html> и <body>Не должен содержать <html> и <body>
Клиентский компонентНе может быть клиентским компонентомМожет быть клиентским компонентом
Область примененияОборачивает все страницы приложенияОборачивает дочерние страницы и Layouts в своем сегменте
layout.tsx
import { Header } from "@/widgets/header/header"
import type { Metadata } from "next"
import { Geist, Geist_Mono } from "next/font/google"
import "./globals.css"
 
const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
})
 
const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
})
 
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
}
 
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="en">
      <body className={`${geistSans.variable} ${geistMono.variable}`}>
        <Header />
        {children}
      </body>
    </html>
  )
}

2.2. Принцип вложенности ("Матрёшка")

Layouts в Next.js работают по принципу "матрёшки": дочерние Layouts вкладываются в родительские, создавая иерархическую структуру UI.

Пример иерархии:

  1. Уровень 1 (Корень): app/layout.tsx с общим хедером
  2. Уровень 2 (Профиль): app/profile/layout.tsx для всех страниц /profile
  3. Уровень 3 (Динамический профиль): app/profile/[slug]/layout.tsx для динамических страниц

При переходе на /profile/123 интерфейс собирается из всех трех уровней. UI рендерится как матрёшка: корневой Layout оборачивает Layout профиля, который оборачивает Layout динамической страницы.

2.3. Сохранение состояния при навигации

Ключевая особенность Layout: состояние и сам компонент сохраняются при навигации между дочерними страницами. Layout не перемонтируется и не перерисовывается.

💡

Профессиональный совет: Используйте Layout для асинхронных запросов данных, которые должны выполняться один раз для целого раздела сайта. Это предотвращает лишние вызовы API при навигации.

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

3. Ключевое различие: Layout против Template

3.1. Фундаментальное отличие в поведении

Основное различие между Layout и Template заключается в управлении состоянием:

  • Layout сохраняет состояние. Он монтируется один раз и не пересоздается при навигации
  • Template создает новый экземпляр компонента при каждой навигации. Его состояние сбрасывается

3.2. Анализ на практическом примере

Сценарий 1: Использование Layout

// app/profile/layout.tsx
"use client"
import { useEffect } from "react"
 
export default function ProfileLayout({ children }) {
  useEffect(() => {
    alert("Layout mounted!")
  }, [])
 
  return <div>{children}</div>
}

Результат эксперимента с Template

Теперь alert будет срабатывать при каждом переходе: и при входе на /profile, и при переходе с /profile на /profile/123, и при возвращении обратно. Это доказывает, что Template перемонтируется при каждой навигации, заново выполняя всю свою логику.

3.3. Сводная таблица и сценарии использования

Синтезируем полученные знания в итоговую таблицу.

КритерийLayout Template
Сохранение состоянияСохраняет состояние между навигациямиСбрасывает состояние при каждой навигации
ПерерисовкаНе перемонтируется при смене дочернего роутаПеремонтируется при каждой смене роута
Основной сценарийСтатичные элементы UI (хедер, сайдбар), запросы данных, которые выполняются один раз на секциюАнимации входа/выхода, логика на основе useEffect, которая должна выполняться при каждой навигации

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

  • Запуск анимаций при переходе между страницами
  • Повторная инициализация сложных клиентских компонентов
  • Сброс состояния формы при навигации

4. Важное замечание для разработчиков: React Strict Mode

В процессе разработки вы можете заметить, что alert из useEffect (или console.log) срабатывает дважды при монтировании компонента. Не стоит беспокоиться — это ожидаемое поведение в режиме разработки (development mode).

Причина: React Strict Mode, который по умолчанию включен в Next.js. Он намеренно дважды рендерит компоненты, чтобы помочь разработчикам выявлять:

  1. Побочные эффекты в компонентах
  2. Потенциальные проблемы в коде
  3. Несоответствия между рендерами

Важно понимать: В финальной, продакшн-сборке (production build) это двойное срабатывание отсутствует.

Временное отключение Strict Mode

Если это поведение мешает отладке, его можно временно отключить:

javascript
// next.config.js
module.exports = {
  reactStrictMode: false, // Внимание: отключайте только для отладки!
}

Ключевой вывод:

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

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