1. Обработка ошибок на уровне компонентов
В реальной жизни даже самые лучшие приложения иногда "падают". Причины могут быть разными: не пришли данные с сервера, кто-то написал баг в компоненте, пользователь ввёл что-то неожиданное или просто интернет внезапно исчез (привет, Wi-Fi в метро).
Если не обрабатывать ошибки, пользователь увидит либо пустую страницу, либо страшный "технический" текст, либо вообще ничего. Это не только портит впечатление, но и усложняет отладку. Хорошая обработка ошибок — это:
- Красивое, дружелюбное сообщение вместо "падения".
- Возможность восстановиться (например, попробовать снова).
- Логирование ошибок для разработчиков.
- Улучшение UX и доверия к вашему продукту.
В классическом React для обработки ошибок используют Error Boundaries — специальные компоненты, которые "ловят" ошибки в дереве под собой и показывают запасной UI. В Next.js 15 концепция та же, но реализовано это через файл с особым именем: error.tsx.
Где размещать error.tsx
- В любой папке внутри app/, где у вас есть маршруты (например, /app/dashboard/error.tsx).
- Работает аналогично layout.tsx или loading.tsx: применяется только к дочерним маршрутам этой папки.
- Если в папке нет своего error.tsx, Next.js ищет его выше по дереву.
Когда срабатывает error.tsx
- Если в Server Component или Client Component произошла ошибка при рендеринге или загрузке данных.
- Если ошибка возникла во время выполнения Server Action.
- Если ошибка возникла в дочерних компонентах или страницах.
Важно: ошибки в layout.tsx или в самом error.tsx не перехватываются этим же error boundary — они "поднимаются" выше.
2. Базовый пример error.tsx
Давайте создадим простую структуру:
app/
dashboard/
page.tsx
error.tsx
Пример error.tsx
'use client'; // обязательно!
import React from "react";
export default function Error({ error, reset }: { error: Error, reset: () => void }) {
return (
<div style={{ padding: 32, textAlign: 'center', color: 'crimson' }}>
<h1>Что-то пошло не так 😬</h1>
<p>{error.message}</p>
<button onClick={reset} style={{ marginTop: 16 }}>
Попробовать снова
</button>
</div>
);
}
Обратите внимание:
- error.tsx должен быть Client Component ('use client'; в первой строке).
- Компонент получает два пропса:
- error — сам объект ошибки (можно показать сообщение, залогировать и т.д.).
- reset — функция, которая "перезапускает" попытку рендера (например, если ошибка была случайной).
Как это работает на практике
Представим, что в вашем page.tsx есть ошибка:
export default function Page() {
throw new Error("Упс! Данные не загрузились.");
return <div>Дашборд</div>;
}
При переходе на этот маршрут Next.js автоматически покажет содержимое error.tsx из этой папки. Пользователь увидит красивое сообщение, а не просто "белый экран".
Можно добавить кнопку "Попробовать снова", которая вызовет функцию reset — Next.js повторно попытается отрендерить страницу. Это удобно, если ошибка была временной (например, сеть восстановилась).
Рекомендации по оформлению error.tsx
- Не пугайте пользователя: не пишите "FATAL ERROR: Cannot read property 'foo' of undefined". Лучше что-то вроде "Извините, возникла ошибка. Пожалуйста, попробуйте ещё раз".
- Добавьте кнопку "Попробовать снова": это стандарт, пользователи ждут такого поведения.
- Логируйте ошибки: можно отправлять ошибки на сервер для анализа (например, через Sentry).
- Сделайте дизайн error.tsx в стиле вашего приложения: чтобы пользователь не думал, что попал на чужой сайт.
3. Вложенность error.tsx и наследование ошибок
В Next.js error boundary работает "по месту": если ошибка произошла в дочернем маршруте, а в нём есть свой error.tsx, будет показан именно он. Если нет — ищется выше по дереву.
app/
error.tsx // ловит все ошибки в app, если ниже нет своего error.tsx
dashboard/
error.tsx // ловит только ошибки в dashboard/*
page.tsx
analytics/
page.tsx // ошибки здесь ловит dashboard/error.tsx
Это удобно: можно делать разные error boundary для разных разделов приложения. Например, в личном кабинете — один дизайн, в публичной части — другой.
Практика: обработка ошибок при загрузке данных
Допустим, у вас есть Server Component, который загружает данные с API:
// app/dashboard/page.tsx
import { fetchStats } from '@/lib/api';
export default async function Page() {
const stats = await fetchStats(); // если тут произойдёт ошибка...
return <div>Статистика: {stats.value}</div>;
}
Если fetchStats выбросит ошибку (например, сервер не ответил), Next.js автоматически покажет error.tsx из папки dashboard. Это избавляет от необходимости писать try/catch в каждом компоненте!
Связь error.tsx с Suspense и loading.tsx
- loading.tsx показывает "скелетон" или индикатор, пока компонент загружается.
- Если во время загрузки возникает ошибка — управление переходит к error.tsx.
- Если всё загрузилось успешно — показывается основной компонент.
Вот так Next.js реализует паттерн "Suspense + Error Boundary" из современного React.
4. Расширенные сценарии: логирование ошибок
В error.tsx можно добавить отправку ошибок на сервер или в сервисы мониторинга (например, Sentry, LogRocket):
'use client';
import { useEffect } from 'react';
export default function Error({ error, reset }) {
useEffect(() => {
// Отправить ошибку на сервер
fetch('/api/log-error', {
method: 'POST',
body: JSON.stringify({ message: error.message, stack: error.stack }),
});
}, [error]);
return (
<div>
<h1>Ой! Что-то пошло не так.</h1>
<button onClick={reset}>Попробовать снова</button>
</div>
);
}
5. Пример: добавляем error.tsx в мини-приложение
Допустим, в вашем приложении есть раздел "Профиль", который иногда не может загрузиться из-за проблем с сервером:
app/
profile/
page.tsx
error.tsx
page.tsx:
export default async function Page() {
// Симулируем ошибку
throw new Error("Не удалось загрузить профиль пользователя.");
}
error.tsx:
'use client';
export default function Error({ error, reset }) {
return (
<div style={{ textAlign: 'center', marginTop: 50 }}>
<h2>Ошибка загрузки профиля</h2>
<p>{error.message}</p>
<button onClick={reset}>Попробовать снова</button>
</div>
);
}
Теперь при ошибке в разделе "Профиль" пользователь увидит понятное сообщение и сможет попробовать ещё раз.
6. Типичные ошибки при работе с error.tsx (Error Boundary)
Ошибка №1: забыли 'use client'
Без этой строки error.tsx просто не работает. Да, Next.js не всегда явно ругается — но boundary не сработает.
Ошибка №2: не реализован reset
Пользователь не может повторить попытку — приходится обновлять страницу вручную. Всегда добавляйте кнопку "Попробовать снова"!
Ошибка №3: показываете слишком "техническое" сообщение
Пользователь не обязан знать, что у вас "TypeError: Cannot read property 'foo' of undefined". Лучше показать дружелюбное сообщение и, если нужно, добавить технические детали для разработчиков (например, под спойлером).
Ошибка №4: error.tsx не в той папке
Если error.tsx лежит не в том месте, где произошла ошибка, boundary не сработает. Проверьте структуру папок.
Ошибка №5: ошибка внутри error.tsx
Если ваш error.tsx сам падает (например, из-за опечатки), Next.js покажет техническую ошибку или "поднимет" boundary выше. Проверяйте error.tsx отдельно!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ