LoginSignup
0
0

More than 1 year has passed since last update.

ErrorBoudaryを関数型コンポーネントとして定義したい

Last updated at Posted at 2022-09-28

ReactのErrorBoundaryとは?

ErrorBoundaryは、子コンポーネントで何らかのエラーが発生した時にエラー画面をフォールバックUIとして表示してくれるコンポーネントです。

2022年8月時点でも、ErrorBoundaryはクラスコンポーネントとして定義する必要があり、現在主流である関数型コンポーネントとして作成することができません。

ErrorBoundaryコンポーネントはクラスコンポーネントに、ライフサイクルメソッドである static getDerivedStateFromError()componentDidCatch() を定義すると、作成する事ができます。

公式ドキュメントからの抜粋
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; 
  }
}

また、イベントハンドラでのエラーや、非同期処理のエラー等、以下は処理することができません。

  • イベントハンドラ
  • setTimeoutなどに代表される非同期コード
  • サーバサイドレンダリング
  • ErrorBoundary自身がスローしたエラー

これらを関数型コンポーネントでうまく扱える方法がないかなぁと探していたところ、react-error-boundaryというパッケージがあり、クラスコンポーネントでは扱えないエラーも簡単に処理できそうだったので、試してみました。

react-error-boundaryを試してみる

react-error-boundaryは、レンダー時のエラーを扱いやすくしてくれるラッパーです。
インストールや基本的な使い方は公式ドキュメントを参照してみて下さい。

エラー発生時に表示するコンポーネントを追加します。
渡ってきたpropsからエラー情報を取得して表示します。

components/ErrorBoundary/index.js
import React from "react";

export const ErrorFallback = ({ error, resetErrorBoundary }) => {
  return (
    <div>
      <h1>エラーが発生しました</h1>
      <p>{error.message}</p>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
};

続いて検証のために、一定の確率でエラーを起こすコンポーネントを作成します。

components/SamplePage/index.js
import React from "react";

export const SamplePage = () => {
  const random = Math.random();

  if (random <= 0.5) {
    throw new Error("Something went wrong");
  }

  return (
    <div>
      <h2>SamplePage</h2>
    </div>
  );
};

最後にフォールバックUIを表示させたいコンポーネントを、react-error-boundaryからimportしたErrorBoundaryでWrapします。

src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import { ErrorBoundary } from "react-error-boundary";
import App from "./App";
import { ErrorFallback } from "./components/ErrorBoundary";

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

これでエラー発生時に代わりのUIを表示する事が出来ました。
gif画像にある「Try againのボタンには、propsのresetErrorBoundaryに指定されているコールバックを実行することで、少し時間を置いてからリカバリーするという選択肢もユーザーに提供する事ができます。(リカバリーする状況であれば)

画面収録 2022-09-27 22.57.00.mov.gif

最後に

ドキュメントを読むと、イベントハンドラや非同期処理のエラーまで扱えるようになるので、クラスコンポーネントのErrorBoundaryで扱えないものも考慮したい場合、手軽に扱えそうなので、良い選択肢だと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0