7. Обработка ошибок
Remix предоставляет отличную систему обработки ошибок. Каждый маршрут может иметь свой ErrorBoundary, который перехватывает ошибки из loader, action и компонента.
ErrorBoundary
Заголовок раздела «ErrorBoundary»import { useRouteError, isRouteErrorResponse } from "@remix-run/react";
export function ErrorBoundary() { const error = useRouteError();
// Ошибки, брошенные как Response (throw new Response(...)) if (isRouteErrorResponse(error)) { return ( <div> <h1>{error.status} {error.statusText}</h1> <p>{error.data}</p> </div> ); }
// Обычные JavaScript ошибки if (error instanceof Error) { return ( <div> <h1>Что-то пошло не так</h1> <p>{error.message}</p> </div> ); }
return <h1>Неизвестная ошибка</h1>;}Типы ошибок
Заголовок раздела «Типы ошибок»1. Response ошибки (HTTP)
Заголовок раздела «1. Response ошибки (HTTP)»export async function loader({ params }) { const user = await getUser(params.id);
if (!user) { throw new Response("Пользователь не найден", { status: 404, statusText: "Not Found", }); }
return json(user);}2. Обычные ошибки
Заголовок раздела «2. Обычные ошибки»export async function loader() { try { return json(await fetchData()); } catch (err) { // Remix перехватит это в ErrorBoundary throw new Error("Ошибка загрузки данных"); }}3. Ошибки в action
Заголовок раздела «3. Ошибки в action»export async function action({ request }) { const data = await request.formData(); const result = await riskyOperation(data.get("id"));
if (!result.ok) { // Возвращаем данные об ошибке (не бросаем) return json({ error: result.message }, { status: 400 }); }
return redirect("/success");}Вложенные ErrorBoundary
Заголовок раздела «Вложенные ErrorBoundary»Ключевое преимущество Remix — ошибки изолируются в своём маршруте:
app/routes/ dashboard.tsx ErrorBoundary здесь... dashboard.users.tsx ...перехватит ошибку здесь dashboard.stats.tsx ...или здесьЕсли dashboard/stats бросает ошибку, ErrorBoundary в dashboard/stats.tsx показывает ошибку только в области статистики, остальная часть dashboard продолжает работать!
Root ErrorBoundary
Заголовок раздела «Root ErrorBoundary»В root.tsx обязательно нужен ErrorBoundary как страховка:
export function ErrorBoundary() { const error = useRouteError();
return ( <html> <head><title>Ошибка</title></head> <body> <div className="error-page"> <h1>Критическая ошибка</h1> {isRouteErrorResponse(error) ? `${error.status}: ${error.statusText}` : "Что-то пошло не так"} </div> </body> </html> );}notFound helper (Remix v2)
Заголовок раздела «notFound helper (Remix v2)»import { data } from "@remix-run/node";
export async function loader({ params }) { const post = await getPost(params.slug);
if (!post) { throw data("Пост не найден", { status: 404 }); }
return { post };}