JavaScript
reactjs
React

React 16でError Boundaryが導入された

More than 1 year has passed since last update.

このスライドについて

  • 弊社(株式会社チームスピリット)のフロントエンドランチネタとして用意したスライドです
  • ブログ にはもうちょっと詳しく書きました

この話

SS 2017-08-02 5.03.45.png

https://facebook.github.io/react/blog/2017/07/26/error-handling-in-react-16.html


これまで

  • コンポーネント内で発生したランタイムエラーをうまくハンドリングする方法が提供されていなかった
  • エラーが発生すると React の内部状態(internal state)も壊れ、結果的によくわからないエラーがコンソールに表示される要因になっていた

(※internal state については訳がおかしいかも)

In the past, JavaScript errors inside components used to corrupt React’s internal state and cause it to emit cryptic errors on next renders.


Error Boundary


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

  /********* これが新しく追加 ************/
  componentDidCatch(error, info) {
    // Display fallback UI
    this.setState({ hasError: true });
    // 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>
  <AddTodo />
  <VisibleTodoList />
  <FilterLinkList />
</ErrorBoundary>

Demo


Error Boundary

  • 子孫コンポーネントツリーで発生したエラーを catch するためのコンポーネント
  • componentDidCatch というライフサイクルメソッドが追加され、子孫コンポーネントツリーで発生したエラーはそこでハンドリングできるように
  • コンポーネントツリー内にいくつでも置ける
    • 独立して動作するUIパーツ単位で Boundary を設けたり

componentDidCatch(error, info)

  • error: Error オブジェクト
  • info: info.componentStack で Component Stack Trace が取れる
    • コンポーネントのどこで発生したエラーか?が追いやすい
in BuggyCounter (created by App)
in ErrorBoundary (created by App)
in div (created by App)
in App

Uncaught Error時の挙動の変更

  • React 15 まではエラーが発生しても UI はそのまま残る(Demo
  • React 16 以降、Uncaught Exception が発生すると コンポーネントツリーが全部 unmount される(非表示になる)Demo

所感

  • Error Boundary の導入によってエラーハンドリング(特に外部へのエラーログ送信など)はやりやすくなった
  • Uncaught Error 時の仕様変更があるので、最低限「ルートに1個 Boundary を追加する」ぐらいはやっておかないといけなさそう