← 記事一覧

Error BoundaryをFunction Componentで扱う

目次

要約

  • React では v16 から React Hooks の登場で Function Component がスタンダードになっている
  • Error Boundary を実装する際はライフサイクルメソッドの static getDerivedStateFromError() か componentDidCatch() のいずれか(または両方)を使わないといけない、つまり Class Component が必須になっている
  • では Error Boundary を Function Component で扱えるラッパーを提供してくれる

Error Boundary とは

React では Error Boundary という子コンポーネントツリーでエラーが発生した際にクラッシュした UI を表示させる代わりに、フォールバック用の UI を表示するコンポーネントがあります。これはユーザーが壊れた画面で操作することにより、サービスに問題が起こることを防ぐことができます。

このようなエラーハンドリングは try/catch で行うことが一般的ですが、これは命令型のコード(関数の実行など)でしか動作しません。そのため、コンポーネントのような宣言型でエラーに応じた処理を行うためには別の方法を取らなければなりません。react ではライフサイクルメソッドのかのいずれか(または両方)を使うことで実装できます。

以下は公式ドキュメントからの抜粋です。

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, errorInfo) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}
// 使い方
<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

これらを関数型でうまく扱える方法がないか探したところ、react-error-boundary というパッケージがありました。
なので実装例とともに紹介します。

Function Component で Error Boundary を試す

というレンダリング時のエラーを扱いやすくするラッパーを提供してくれています。
試しに定期的にエラーを引き起こすコンポーネントを作成します。

import React from "react";
import ReactDOM from "react-dom";

// 定期的にエラーを起こすコンポーネント
const App: React.FC = () => {
  const rnd = Math.random();
  if (rnd <= 0.7) {
    throw new Error("Something went wrong!");
  }
  return <div>OK</div>;
};

ReactDOM.render(<App />, document.getElementById("root"));

現状のままだと <App /> がエラーを出した場合、真っ白な画面(壊れた UI)が表示されてしまいます。

react-error-boundary を使うことでエラー時のコンポーネントを関数コンポーネントとして別に用意し、エラー時のフォールバック用のコンポーネントとして表示できます。以下が簡単な実装例です。

import React from "react";
import ReactDOM from "react-dom";

import { ErrorBoundary, FallbackProps } from "react-error-boundary";

// 定期的にエラーを起こすコンポーネント
const App: React.FC = () => {
  const rnd = Math.random();
  if (rnd <= 0.7) {
    throw new Error("Something went wrong!");
  }
  return <div>OK</div>;
};

// エラー時のフォールバック用のコンポーネント
const ErrorFallback: React.FC<FallbackProps> = ({ error, resetErrorBoundary }) => {
  return (
    <div role="alert">
      <p>Error Message</p>
      <pre>{error!.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
};

ReactDOM.render(
  <ErrorBoundary FallbackComponent={ErrorFallback}>
    <App />
  </ErrorBoundary>,
  document.getElementById("root")
);

これによりエラーの際に、<ErrorFallback/> で定義した代わりの UI を表示させることができます。

エラー時の代替UI。「Error Message」「Something went wrong!」と表示され、再試行用の「Try again」ボタンがある

より詳しく知りたい方は参考資料をご覧ください。

参考資料

コメント・リアクション

GitHub アカウントで、感想やリアクションを残せます。

表示されない場合は、GitHub でコメントを見る

← 記事一覧へ戻る