[React翻譯]Error Boundaries(錯誤邊界)

Error Boundaries(錯誤邊界)

介紹

UI的某一部分拋錯不該該致使整個App都崩掉,React 16由此提出一個新概念叫「error boundary」,錯誤邊界html

「error boundary」是什麼呢,是一個React組件。error boundary能捕獲子組件樹中發生的任何錯誤,而後打日誌,返回fallback UI。react

error boundary能捕獲哪兒的錯誤:git

  1. render裏
  2. 生命週期方法裏的
  3. 子組件樹的constructor裏的

error boundary不能捕獲哪兒的錯誤:github

  1. 事件處理程序的錯(learn more)
  2. 異步代碼的錯 (e.g. setTimeout or requestAnimationFrame callbacks)
  3. ssr的錯
  4. error boundary自個兒的錯

若是一個組件定義了static getDerivedStateFromError()或componentDidCatch()或兩個都有,那麼這個組件就是一個error boundary。npm

static getDerivedStateFromError()用於拋錯後返回fallback UI,componentDidCatch()用於打錯誤日誌瀏覽器

下面舉個例子babel

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}
複製代碼

而後就能把組件在ErrorBoundary裏就能夠了app

<ErrorBoundary>
  <MyWidget /> </ErrorBoundary>
複製代碼

ErrorBoundary至關於組件的catch{}塊。只要class型的組件能用ErrorBoundary,function型的不能用。異步

一般實踐推薦在App裏一處定義,到處使用ide

注意,ErrorBoundary只catch它子組件的錯,它自個兒的錯不catch。固然了,若是ErrorBoundary拋錯了那它會傳到它上面的ErrorBoundary去處理。

例子

Check out this example of declaring and using an error boundary with React 16.

Error Boundaries放哪好呢?

隨便,看你怎麼寫。包裹整個APP也成,包裹一個小組件也成

未捕獲錯誤的新行爲

這個變化意義重大。對於React 16來講,未被Error Boundaries捕獲的錯誤會 unmount 整個react組件樹

爲啥這麼作呢?React的人認爲,寧肯我給整個APP都掛掉也比返一個部分掛掉的UI強。比方說通訊類app,一個掛掉的UI可能致使信息發錯人;再比方說支付類APP,顯示錯誤的帳戶餘額還不如啥都不顯示

多用Error Boundaries更帶來更好的用戶體驗。Facebook Messenger 給sidebar,info panel,conversation log都各自包了一層ErrorBoundary,這樣某個組件掛了不會影響其餘的,並且能展現不一樣的fallback UI

推薦你用一些JS錯誤彙報工具

組件堆棧跟蹤

Error caught by Error Boundary component

Create React App默認配置的,若是沒用要加 this plugin到babel。

開發環境使用,生產環境禁用!

組件堆棧跟蹤的組件名是調Function.name 獲得的,低版本瀏覽器本身polyfill

How About try/catch?

try/catch只適用於當即執行的代碼

try {
  showButton();
} catch (error) {
  // ...
}
複製代碼

可是react組件是聲明式的,說明將要渲染什麼,Error boundaries保留了react聲明式的特色

blabalbla...

關於Event Handlers

Error boundaries do not catch errors inside event handlers!

渲染的時候不會處理事件的,因此事件處理程序拋錯react會知道的。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    try {
      // Do something that could throw
    } catch (error) {
      this.setState({ error });
    }
  }

  render() {
    if (this.state.error) {
      return <h1>Caught an error.</h1>
    }
    return <div onClick={this.handleClick}>Click Me</div>
  }
}
複製代碼

關於React 15的名稱變化

unstable_handleError 改爲了 componentDidCatch

這部分變化codemod能夠幫你自動遷移代碼

相關文章
相關標籤/搜索