iT邦幫忙

2021 iThome 鐵人賽

DAY 22
0
自我挑戰組

React 學習之路系列 第 22

[進階指南] 錯誤邊界 ( Day22 )

  • 分享至 

  • xImage
  •  

component 裡 JavaScript 的錯誤常常會破壞 React 的內部 state,並使它在下次 render 的時候發生 神秘的 錯誤。這些錯誤總是被應用程式的程式碼裡更早發生的錯誤所導致,但 React 並沒有提供在 component 裡優雅處理它們的方式,而且也無法從錯誤中恢復。

JavaScript 發生的錯誤,會導致 React 在 render 的時候、生命週期函式內、或底下一整個 component tree 裡的 Class constructor 發生錯誤。所以 React 以 錯誤邊界 進行處理,捕抓記錄那些錯誤,然後顯示在一個 fallback 的使用介面。

  1. React 15 引入了的 unstable_handleError 函式,React 16 正式引入「錯誤邊界」概念,並改名為 componentDidCatch。
  2. 錯誤邊界處理使用 Class component ,如果使用 Hook 擇可用 ErrorBoundary 包裹替代。
  3. Class component 裡定義 componentDidCatch() 或 static getDerivedStateFromError() 進行錯誤邊界的處理跟錯誤的追蹤

建立 ErrorBoundary Component

  1. 建立一個 ErrorBoundary 的 Component
  2. 確認 ErrorBoundary 不會有任何的問題
  3. 當一般 Component 使用
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>

測試有錯誤邊界 VS 沒錯誤邊界

錯誤邊界的設計防止一個元件發生錯誤造成整個應用程式壞掉。

沒錯誤邊界

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


上一篇
第一個 HOC (Higher-Order Components)( Day21 )
下一篇
[進階指南] Fragments( Day23 )
系列文
React 學習之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言