為什麼誤差邊界很重要
在 React 應用程式中,元件中一個未捕獲的 JavaScript 錯誤可能會導致整個 UI 崩潰。在錯誤邊界之前,這表示使用者會看到一個白屏,沒有任何錯誤提示。錯誤邊界是 React 元件,可以捕捉子元件樹中任何位置的 JavaScript 錯誤,並呈現後備 UI,而不是崩潰。
實現誤差邊界
錯誤邊界是實作靜態生命週期方法 getDerivedStateFromError 和 componentDidCatch 之一或兩者的類別元件:
import React, { Component, ErrorInfo, ReactNode } from "react";
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error: Error | null;
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, info: ErrorInfo) {
console.error("Error caught:", error, info.componentStack);
// Send to logging service
logErrorToService(error, info);
}
render() {
if (this.state.hasError) {
return this.props.fallback || <DefaultFallback error={this.state.error} />;
}
return this.props.children;
}
}
後備 UI 設計
良好的後備 UI 提供恢復選項並減少使用者的挫折感:
function DefaultFallback({ error }: { error: Error | null }) {
return (
<div role="alert" className="error-boundary-fallback">
<h2>Something went wrong</h2>
<p>We encountered an unexpected error. Please try refreshing the page.</p>
<button onClick={() => window.location.reload()}>
Refresh Page
</button>
{process.env.NODE_ENV === "development" && (
<pre>{error?.message}</pre>
)}
</div>
);
}
與日誌服務整合 (Sentry)
錯誤邊界與 Sentry 等錯誤監控工具自然整合:
import * as Sentry from "@sentry/react";
class SentryErrorBoundary extends Component<Props, State> {
componentDidCatch(error: Error, info: ErrorInfo) {
Sentry.withScope((scope) => {
scope.setExtras({ componentStack: info.componentStack });
Sentry.captureException(error);
});
}
}
Sentry 還提供了一個內建的錯誤邊界包裝器:
<Sentry.ErrorBoundary fallback={<ErrorFallback />}>
<App />
</Sentry.ErrorBoundary>
邊界放置策略
錯誤邊界的策略佈局至關重要:
App
├── ErrorBoundary (global fallback)
│ ├── Layout
│ │ ├── Header
│ │ ├── ErrorBoundary (content area fallback)
│ │ │ ├── MainContent
│ │ │ └── DataTable
│ │ └── Footer
│ └── ErrorBoundary (sidebar fallback)
│ └── SidebarWidget
指南:
- 獨立包裝每個主要部分(側邊欄、主要內容、模式)
- 僅將根邊界用作最後的手段
- 將邊界放置在故障可恢復的特徵邊界處
- 允許 UI 的正常部分保持功能
錯誤恢復模式
除了顯示回退之外,錯誤邊界還可以提供恢復:
class RecoverableBoundary extends Component {
state = { hasError: false, error: null };
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
handleRetry = () => {
this.setState({ hasError: false, error: null });
};
render() {
if (this.state.hasError) {
return (
<div>
<p>Error: {this.state.error?.message}</p>
<button onClick={this.handleRetry}>Retry</button>
</div>
);
}
return this.props.children;
}
}
限制
誤差邊界有需要理解的重要限制:
| 限制 | 說明 |
|---|---|
| 事件處理程序 | onClick 等中的錯誤不會被捕獲 - 使用 try-catch |
| 非同步程式碼 | setTimeout 或 Promise 錯誤未被捕獲 |
| 固態繼電器 | 錯誤邊界不會捕獲伺服器端錯誤 |
| 自己的錯誤 | 錯誤邊界無法捕獲其自身的錯誤 |
| 狀態突變 | 並非旨在處理損壞的全域狀態 |
結論
錯誤邊界是生產 React 應用程式的重要組成部分。它們可以防止 UI 完全崩潰,提供優雅的降級,並與日誌記錄服務無縫整合。透過將戰略邊界放置與正確的錯誤日誌記錄和復原模式相結合,您可以建立能夠優雅地處理故障並為開發人員提供可操作診斷的應用程式。

