使用錯誤邊界 (error boundaries) 的最佳實踐來處理 React 中的錯誤

當在組件中發生錯誤時,React 會卸載整個 React 組件樹,渲染出「空白」的頁面。這是 React 處理崩潰的方式。

您不希望錯誤顯示給用戶。React 選擇顯示空白頁面。

然而,這只是默認行為。讓空白頁面出現只比給用戶顯示晦澀的訊息好一點,但您應該找到更好的方式。

如果您處於開發模式,任何錯誤將觸發詳細的堆棧跟踪信息顯示到瀏覽器的開發工具控制台中。但在正式環境中,您不想把錯誤訊息直接印給用戶。

在正式環境中,您應該攔截錯誤,並向用戶顯示某種有用的訊息。

這就是「錯誤邊界」 (error boundaries) 發揮作用的地方。

使用錯誤邊界,您可以分離應用的各個部分並在本地處理錯誤。

錯誤邊界是一個實現了 componentDidCatch() 生命周期事件的 React 組件,並將其他組件封裝在內:

class ErrorHandler extends React.Component {
 constructor(props) {
 super(props)
 this.state = { errorOccurred: false }
 }

 componentDidCatch(error, info) {
 this.setState({ errorOccurred: true })
 logErrorToMyService(error, info)
 }

 render() {
 return this.state.errorOccurred ? <h1>出現錯誤了!</h1> : this.props.children
 }
}

然後在組件的 JSX 中以以下方式使用它:

<ErrorHandler>
 <SomeOtherComponent />
</ErrorHandler>

SomeOtherComponent 或其他子組件中發生錯誤時,以及它們擁有的整個組件子樹中發生的錯誤,ErrorHandler 將攔截並使您能夠優雅地處理錯誤。

在上面的例子中,靈感來自 React 官方文件。我們有一個名為 errorOccurred 的狀態屬性,當設置為 true 時,界面會渲染錯誤處理的使用者界面,否則渲染正常的應用程式使用者界面。

componentDidCatch() 內,它接收了描述錯誤的兩個參數,我們也調用了 logErrorToMyService(),這只是一個使用 Sentry、Roller、Airbrake 或其他能夠以便於閱讀的方式記錄錯誤的服務的存根函數,這樣您就不必依賴用戶通知您存在錯誤才能注意到問題。