為了避免向使用者呈現空白頁面,路由模組會自動捕獲您程式碼中的錯誤,並渲染最近的 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 找不到渲染頁面所需的內容時,您可以故意向最近的錯誤邊界拋出 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)
發送的資料不會被清理,因為那裡的資料旨在被渲染。