为了避免向用户渲染空白页面,路由模块将自动捕获代码中的错误,并渲染最近的 ErrorBoundary
。
错误边界并非旨在用于错误报告或渲染表单验证错误。请参阅表单验证和错误报告。
所有应用程序至少应导出一个根错误边界。这一个处理三种主要情况
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
分支。
这不仅适用于 loaders,而且适用于所有路由模块 API:loaders、actions、components、headers、links 和 meta。
规则 #2 有例外情况,尤其是 404。当您的 loader 找不到渲染页面所需的内容时,您可以有意 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)
发送的数据不会被清理,因为那里的数据旨在被渲染。