component 裡 JavaScript 的錯誤常常會破壞 React 的內部 state,並使它在下次 render 的時候發生 神秘的 錯誤。這些錯誤總是被應用程式的程式碼裡更早發生的錯誤所導致,但 React 並沒有提供在 component 裡優雅處理它們的方式,而且也無法從錯誤中恢復。
JavaScript 發生的錯誤,會導致 React 在 render 的時候、生命週期函式內、或底下一整個 component tree 裡的 Class constructor 發生錯誤。所以 React 以 錯誤邊界 進行處理,捕抓記錄那些錯誤,然後顯示在一個 fallback 的使用介面。
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 更新 state 以至於下一個 render 會顯示 fallback UI
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 你也可以把錯誤記錄到一個錯誤回報系統服務
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// 你可以 render 任何客製化的 fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
引用 Component 結構如下
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
錯誤邊界的設計防止一個元件發生錯誤造成整個應用程式壞掉。
沒錯誤邊界
Codepen 完整例子
有錯誤邊界
Codepen 完整例子
錯誤邊界就如同 JavaScript 的 catch {},但它是給 component 使用的。只有 class component 可以成為錯誤邊界。實務上,大部分的時間你只會想要宣告錯誤邊界 component 一次,然後在你的應用程式裡重複使用它。
要注意錯誤邊界只會捕捉它底下 component tree 裡的 component 的錯誤。
該把錯誤邊界放在哪裡
任何需要他的地方,route component 或是其他小工具外面。
對於未捕捉到的錯誤的新行為
在 React 16,沒有被錯誤邊界所捕捉到的錯誤會 unmount 整個 React component tree。
Component Stack Traces
Create React App 建立專案的話,預設會顯示錯誤。但如果是自己建專案引用 React 可在 bible 上加入 @babel/plugin-transform-react-jsx-source 插件。
try/catch
只作用在命令式程式碼(imperative code)
Event Handler
在 event handler 裡面發生的 JS 錯誤,錯誤邊界並不會抓取。但如果因為裡面造成的渲染錯誤,錯誤邊界依然會處理。
handleClick = () => {
//一樣會造成 render 錯誤
try {
this.setState(() => Ghost);
} catch (error) {
console.log(error)
}
}
以上今天
參考資料:
https://zh-hant.reactjs.org/docs/error-boundaries.html