К содержанию

Загрузка, ошибки и страница «Не найдено»

Отличаем ожидание, пустой результат, неизвестный адрес и сбой.

На этой странице

Для Next.js 16.3.8 (App Router) и React 19.3.0. Обновлено .

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

Выберите состояние интерфейса

Кинопоказ

19:00. Билет: 300 ₽.

Это схема: переключение не отправляет запросы. В приложении состояние определяется результатом загрузки.

В этом примере можно выбирать состояние страницы и сравнивать сообщения и кнопки. Переключатель не отправляет сетевые запросы.

loading.tsx: результат ещё готовится

Сохраните каталог с loadEvents из предыдущей статьи. Создайте рядом:

app/events/loading.tsx
export default function Loading() {
  return <p role="status">Загружаем афишу…</p>;
}

Next.js показывает содержимое loading.tsx, пока страница загружается. Общая навигация из layout может оставаться видимой. Когда страница готова, React показывает её вместо сообщения о загрузке.

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

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

Пустой список – допустимый результат

В фильтре уже есть проверка visible.length === 0. Для полностью пустой афиши подходит «Пока мероприятий нет». Если события есть, но не подошли фильтру, точнее «По этому фильтру ничего не найдено» с кнопкой очистки фильтра.

Не показывайте красную ошибку лишь потому, что массив пуст. Запрос мог выполниться успешно и вернуть пустой массив.

notFound: такого мероприятия нет

В динамической странице уже вызывается notFound() для неизвестного id. Добавьте её интерфейс:

app/events/[id]/not-found.tsx
import Link from "next/link";
 
export default function NotFound() {
  return (
    <main>
      <h1>Мероприятие не найдено</h1>
      <p>Проверьте адрес или выберите событие из афиши.</p>
      <Link href="/events">Открыть афишу</Link>
    </main>
  );
}

Для проверки откройте /events/99. Ошибка источника данных не доказывает, что мероприятия нет: при ней нужен интерфейс сбоя, а не notFound().

error.tsx: непредвиденный сбой

В loadEvents после задержки временно добавьте throw new Error("Учебный сбой загрузки"). Для её отображения создайте:

app/events/error.tsx
"use client";
 
export default function ErrorPage({ retry }: { retry: () => void }) {
  return (
    <section role="alert">
      <h2>Не удалось загрузить афишу</h2>
      <p>Попробуйте ещё раз немного позже.</p>
      <button type="button" onClick={() => retry()}>
        Повторить
      </button>
    </section>
  );
}

error.tsx – клиентский компонент, который Next.js показывает при сбое. В Next.js 16.3 функция retry заново получает данные и пытается показать ту часть страницы, где произошла ошибка. Если причина сбоя осталась, снова появится сообщение об ошибке. В старых примерах встречается reset: он сбрасывает состояние ошибки, но не получает серверные данные заново.

Не показывайте пользователю исходный текст серверной ошибки: в нем могут оказаться внутренние данные приложения. Подробности ошибки смотрите в терминале и журнале сервера. В режиме разработки Next.js дополнительно показывает диагностическое окно; в готовом приложении его нет.

Проверьте четыре случая

СценарийОжидаемый интерфейс
Данные ещё не полученыЗагрузка, затем результат
Получен пустой массивСообщение об отсутствии событий
Запрошен неизвестный idСтраница «Мероприятие не найдено»
Загрузка завершилась исключениемСообщение о сбое и повтор

Верните исправный loadEvents после проверки. Далее оформим эти состояния в Next-03.

Документация: loading, ошибки, notFound.