錯誤邊界
在本頁面上

錯誤邊界

為了避免向使用者呈現空白頁面,路由模組會自動捕獲您程式碼中的錯誤,並渲染最近的 ErrorBoundary

錯誤邊界不適用於錯誤報告或渲染表單驗證錯誤。請改為參閱表單驗證錯誤報告

1. 新增根錯誤邊界

所有應用程式至少應匯出一個根錯誤邊界。這個錯誤邊界處理三個主要案例

  • 拋出的 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>;
  }
}

2. 撰寫一個錯誤

不建議故意拋出錯誤以強制錯誤邊界渲染,作為控制流程的一種手段。錯誤邊界主要用於捕獲您程式碼中非故意的錯誤。

export async function loader() {
  return undefined();
}

這將渲染步驟 1 中 UI 的 instanceof Error 分支。

這不僅適用於 loaders,也適用於所有路由模組 API:loaders、actions、components、headers、links 和 meta。

3. 在 loaders/actions 中拋出資料

#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 分支。

4. 巢狀錯誤邊界

當拋出錯誤時,將渲染「最近的錯誤邊界」。考慮以下巢狀路由

// ✅ 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) 發送的資料不會被清理,因為那裡的資料旨在被渲染。

文件和範例 CC 4.0