В React Router начиная с версии 6 введена концепция
errorElement, которая позволяет централизованно
обрабатывать ошибки, возникающие на уровне маршрутов. Этот компонент
выступает аналогом классических обработчиков ошибок в других фреймворках
и обеспечивает гибкое управление отображением ошибок при навигации,
загрузке данных или рендеринге компонентов.
errorElement используется в объекте маршрута
(RouteObject) и представляет собой React-компонент, который
будет рендериться при возникновении ошибок внутри соответствующего
маршрута. Ошибки могут быть двух типов:
loader маршрута.Пример базового использования:
import { createBrowserRouter, RouterProvider } from "react-router-dom";
function Root() {
return <h1>Главная страница</h1>;
}
function ErrorPage({ error }) {
return (
<div>
<h2>Произошла ошибка!</h2>
<p>{error.message}</p>
</div>
);
}
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
errorElement: <ErrorPage />,
},
]);
function App() {
return <RouterProvider router={router} />;
}
В этом примере компонент ErrorPage автоматически
отображается, если любой код маршрута / выбросит
исключение.
Компонент errorElement получает специальный объект через
хук useRouteError(). Он содержит информацию о возникшей
ошибке:
status — HTTP-статус ошибки (если она была выброшена в
loader или action).statusText — описание статуса.message — текст ошибки, если он был передан при
выбросе.stack — стек вызовов для отладки (не рекомендуется
показывать пользователям в продакшн).Пример использования:
import { useRouteError } from "react-router-dom";
function ErrorPage() {
const error = useRouteError();
console.error(error);
return (
<div>
<h1>Ошибка {error.status || "неизвестная"}</h1>
<p>{error.statusText || error.message}</p>
</div>
);
}
loader) и действий (action)loader и action могут выбрасывать объекты
Response, ошибки или строки. React Router автоматически
передаст их в errorElement. Например:
async function loader() {
const response = await fetch("/api/data");
if (!response.ok) {
throw new Response("Данные не найдены", { status: 404 });
}
return response.json();
}
Если loader выбрасывает Response, компонент
errorElement сможет получить статус через
error.status и текст через
error.statusText.
errorElementКаждый маршрут может иметь свой errorElement. Если
ошибка возникает в дочернем маршруте, сначала проверяется его
собственный errorElement. Если он отсутствует, ошибка
поднимается выше по дереву маршрутов, пока не будет найден
обработчик.
Пример вложенной структуры:
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
errorElement: <RootError />,
children: [
{
path: "dashboard",
element: <Dashboard />,
errorElement: <DashboardError />,
},
],
},
]);
Dashboard отобразит
DashboardError.Root (например, в Root.loader)
отобразит RootError.DashboardError отсутствует, будет показан
RootError.Компонент errorElement может содержать любую разметку и
стили, так же как обычный React-компонент. Это позволяет создавать
полноценные страницы ошибок с навигацией, кнопками возврата и адаптивным
дизайном.
function ErrorPage() {
const error = useRouteError();
return (
<div style={{ padding: "2rem", textAlign: "center" }}>
<h1>Упс!</h1>
<p>{error.status ? `Код: ${error.status}` : error.message}</p>
<button onCl ick={() => window.history.back()}>Назад</button>
</div>
);
}
loader и action обрабатываются
синхронно и асинхронно одинаково.element) обрабатываются через ErrorBoundary,
который React Router реализует под капотом.errorElement работает только для ошибок внутри
маршрута; глобальные ошибки вне маршрутов требуют отдельного
управления.1. Динамические ошибки на основе статуса:
function ErrorPage() {
const error = useRouteError();
if (error.status === 404) {
return <p>Страница не найдена</p>;
} else if (error.status === 500) {
return <p>Внутренняя ошибка сервера</p>;
}
return <p>Произошла неизвестная ошибка</p>;
}
2. Обработка ошибок с возможностью повторной загрузки данных:
function ErrorPage() {
const error = useRouteError();
const navigate = useNavigate();
return (
<div>
<p>{error.message}</p>
<button onCl ick={() => navigate(0)}>Попробовать снова</button>
</div>
);
}
Использование errorElement делает структуру маршрутов
более устойчивой к ошибкам и позволяет создавать единообразные страницы
ошибок без дублирования логики во всех компонентах. В сочетании с
loader и action это обеспечивает мощный
механизм обработки ошибок на уровне маршрутов.