Загрузка, ошибки и страница «Не найдено»
Отличаем ожидание, пустой результат, неизвестный адрес и сбой.
On this page
Для Next.js 16.3.8 (App Router) и React 19.3.0. Обновлено .
Пользователь должен понимать, что происходит с афишей. Пустой список, неизвестный идентификатор и сбой источника – разные ситуации. У каждой свое сообщение и подходящее действие.
Выберите состояние интерфейса
Кинопоказ
19:00. Билет: 300 ₽.
Это схема: переключение не отправляет запросы. В приложении состояние определяется результатом загрузки.
В этом примере можно выбирать состояние страницы и сравнивать сообщения и кнопки. Переключатель не отправляет сетевые запросы.
loading.tsx: результат ещё готовится
Сохраните каталог с loadEvents из предыдущей статьи. Создайте рядом:
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. Добавьте её интерфейс:
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("Учебный сбой загрузки"). Для её отображения создайте:
"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.