JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Обработка ошибок: error.tsx<...

Обработка ошибок: error.tsx (Error Boundary) в Next.js

Модуль 4: Node.js, Next.js и Angular
9 уровень , 4 лекция
Открыта

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 отдельно!

3
Опрос
Загрузка данных в Server Components, 9 уровень, 4 лекция
Недоступен
Загрузка данных в Server Components
Загрузка данных в Server Components
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ