ユーザーに空のページが表示されるのを避けるため、ルートモジュールはコード内のエラーを自動的にキャッチし、最も近いErrorBoundary
をレンダリングします。
エラー境界は、エラー報告やフォーム検証エラーのレンダリングを目的としたものではありません。代わりに、フォーム検証とエラー報告を参照してください。
すべてのアプリケーションは、少なくともルートエラー境界をエクスポートする必要があります。これは、次の3つの主要なケースを処理します。
data
import { Route } from "./+types/root";
export function ErrorBoundary({
error,
}: Route.ErrorBoundaryProps) {
if (isRouteErrorResponse(error)) {
return (
<>
<h1>
{error.status} {error.statusText}
</h1>
<p>{error.data}</p>
</>
);
} else if (error instanceof Error) {
return (
<div>
<h1>Error</h1>
<p>{error.message}</p>
<p>The stack trace is:</p>
<pre>{error.stack}</pre>
</div>
);
} else {
return <h1>Unknown Error</h1>;
}
}
制御フローの手段として、意図的にエラーをスローしてエラー境界を強制的にレンダリングすることはお勧めしません。エラー境界は、主にコード内の意図しないエラーをキャッチするためのものです。
export async function loader() {
return undefined();
}
これは、手順1のUIのinstanceof Error
ブランチをレンダリングします。
これはローダーだけでなく、すべてのルートモジュールAPI(ローダー、アクション、コンポーネント、ヘッダー、リンク、メタ)に適用されます。
特に404の場合、#2のルールには例外があります。ローダーがページをレンダリングするために必要なものを見つけられない場合は、意図的にthrow data()
(適切なステータスコード付き)を最も近いエラー境界にスローできます。 404をスローして次に進みます。
import { data } from "react-router";
export async function loader({ params }) {
let record = await fakeDb.getRecord(params.id);
if (!record) {
throw data("Record Not Found", { status: 404 });
}
return record;
}
これは、手順1のUIのisRouteErrorResponse
ブランチをレンダリングします。
エラーがスローされると、「最も近いエラー境界」がレンダリングされます。これらのネストされたルートを検討してください。
// ✅ has error boundary
route("/app", "app.tsx", [
// ❌ no error boundary
route("invoices", "invoices.tsx", [
// ✅ has error boundary
route("invoices/:id", "invoice-page.tsx", [
// ❌ no error boundary
route("payments", "payments.tsx"),
]),
]),
]);
次の表は、エラーの発生元を考慮して、どのエラー境界がレンダリングされるかを示しています。
エラー発生元 | レンダリングされる境界 |
---|---|
app.tsx | app.tsx |
invoices.tsx | app.tsx |
invoice-page.tsx | invoice-page.tsx |
payments.tsx | invoice-page.tsx |
本番モードでは、サーバーで発生したエラーは、機密性の高いサーバー情報(スタックトレースなど)の漏洩を防ぐために、ブラウザーに送信される前に自動的にサニタイズされます。
これは、スローされたError
が、本番環境のブラウザーでは汎用メッセージを持ち、スタックトレースを持たないことを意味します。元のエラーはサーバー上では変更されません。
また、throw data(yourData)
で送信されたデータは、レンダリングされることを意図しているため、サニタイズされないことに注意してください。