精讀《React Error Boundaries》

1 引言

Error Boundaries 是 React16 提出來用來捕獲渲染時錯誤的概念,今天咱們一塊兒讀一讀 A Simple Guide to Error Boundaries in React 這篇文章,瞭解一下這個重要機制。html

2 概述

Error Boundaries 能夠用來捕獲渲染時錯誤,API 以下:前端

class MyErrorBoundary extends Component {
  state = {
    error: null,
  };

  static getDerivedStateFromError(error) {
    // 更新 state,下次渲染能夠展現錯誤相關的 UI
    return { error: error };
  }

  componentDidCatch(error, info) {
    // 錯誤上報
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.error) {
      // 渲染出錯時的 UI
      return <p>Something broke</p>;
    }
    return this.props.children;
  }
}
複製代碼
  • static getDerivedStateFromError: 在出錯後有機會修改 state 觸發最後一次錯誤 fallback 的渲染。
  • componentDidCatch: 用於出錯時反作用代碼,好比錯誤上報等。

這兩種方法中任意一個被定義時,這個組件就會成爲 Error Boundary 組件,能夠阻止子組件渲染時報錯。react

最後做者還提出一個建議,建議將 Error Boundary 單獨做爲一個組件,而不是將錯誤監聽方法與業務組件耦合,一方面考慮到複用,另外一方面則由於錯誤檢測只對子組件生效。git

好吧,其實 React 官方文檔比這篇文章介紹的詳細的多得多,原文介紹到此結束。github

3 精讀

React Error Boundaries 官方文檔 裏提到了四種沒法 Catch 的錯誤場景:微信

  1. 回調事件。因爲回調事件執行時機不在渲染週期內,所以沒法被 Error Boundary Catch 住,若有必要得自行 try/catch。
  2. 異步。好比 setTimeoutrequestAnimationFrame,和第一條同理。
  3. 服務端渲染。
  4. Error Boundary 組件自身觸發的錯誤。由於只能捕獲其子組件的錯誤。

這也是使用 Error Boundaries 最容易有疑問的地方。除了上面的狀況,筆者結合自身經驗再列舉幾種異常邊界場景。框架

沒法捕獲編譯時錯誤

很明顯,即使是 React 官方 API Error Boundary 也只能捕獲運行時錯誤,而對編譯時錯誤無能爲力。異步

編譯時錯誤包括不限於編譯環境錯誤、運行前的框架錯誤檢查提示、TS/Flow 類型錯誤等,這些都是 Error Boundary 沒法捕獲的,並且沒有更好的辦法 Catch 住,遇到編譯錯誤就在編譯時解決吧,僅關注運行時錯誤就行了。ide

能夠做用於 Function Component

雖然函數式組件沒法定義 Error Boundary,但 Error Boundary 能夠捕獲函數式組件的錯誤,所以能夠曲線救國:函數

// ErrorBoundary 組件
class ErrorBoundary extends React.Component {
  // ...
}

// 能夠捕獲全部組件異常,包括 Function Component 的子組件
const App = () => {
  return (
    <ErrorBoundary> <Child /> </ErrorBoundary>
  );
};
複製代碼

對 Hooks 也可生效

對於 Hooks 中異常也能夠生效,好比下面的代碼:

const Child = (props) => {
  React.useEffect(() => {
    console.log(1);
    props.a.b;
    console.log(2);
  }, [props.a.b]);

  return <div />; }; 複製代碼

要注意的是,出如今 deps 中的錯誤會當即被 Catch,致使 console.log(1) 都沒法打印。但若是是下面的代碼,則能夠打印出 console.log(1),沒法打印出 console.log(2):

const Child = (props) => {
  React.useEffect(() => {
    console.log(1);
    props.a.b;
    console.log(2);
  }, []);

  return <div />; }; 複製代碼

因此 React 官網的這句話並非指 Error Boundary 對 Hooks 不生效,而是指 Error Boundary 沒法以 Hooks 方式指定,對功能是沒有影響的:

componentDidCatch and getDerivedStateFromError: There are no Hook equivalents for these methods yet, but they will be added soon.

因此這裏的理解要注意一下,另外 React 官方文檔 Hooks FQA 有不少寶藏,建議抽時間逐條閱讀。

4 總結

Error Boundary 能夠捕獲全部子元素渲染時異常,包括 render、各生命週期函數,但也有不少使用限制,但願你能夠正確使用它。

錯誤捕獲也不是萬能的,更多時候咱們要避免並及時修復錯誤,經過錯誤捕獲下降出錯時對用戶體驗的影響,並在第一時間內監控起來並快速修復。

最後,你有明明正確使用了 Error Boundary 卻依然沒法 Catch 住的錯誤 Case 嗎?

討論地址是:精讀《React Error Boundaries》 · Issue #246 · dt-fe/weekly

若是你想參與討論,請 點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。

關注 前端精讀微信公衆號

版權聲明:自由轉載-非商用-非衍生-保持署名(創意共享 3.0 許可證

相關文章
相關標籤/搜索