ReactのErrorBoundaryを徹底解説!【初心者向け】

こんにちは!今回は、Reactアプリケーションでエラーハンドリングを簡単に行えるライブラリ「react-error-boundary」のErrorBoundaryコンポーネントについて、初心者向けに詳しく解説します。

ErrorBoundaryとは?

ErrorBoundaryは、Reactアプリケーション内で発生するJavaScriptエラーをキャッチし、エラーによってクラッシュしたUIの代わりにフォールバックUI(エラーメッセージなど)を表示するためのコンポーネントです。

Reactには標準でエラー境界(Error Boundary)の機能がありますが、react-error-boundaryライブラリを使用すると、より柔軟で強力なエラーハンドリングが可能になります。

基本的な使い方

まず、react-error-boundaryをインストールします。

npm install react-error-boundary

次に、ErrorBoundaryコンポーネントをインポートし、エラーをキャッチしたいコンポーネントをErrorBoundaryでラップします。

import React from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import MyComponent from './MyComponent';

function ErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div role="alert">
      <p>エラーが発生しました:</p>
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>再試行</button>
    </div>
  );
}

function App() {
  return (
    <ErrorBoundary
      FallbackComponent={ErrorFallback}
      onReset={() => {
        // リセット時の処理をここに記述
      }}
    >
      <MyComponent />
    </ErrorBoundary>
  );
}

export default App;

説明

  • ErrorFallbackコンポーネント: エラー発生時に表示するフォールバックUIを定義します。errorオブジェクトからエラーメッセージを取得し、ユーザーに表示します。また、resetErrorBoundary関数を使用してエラー状態をリセットできます。
  • ErrorBoundaryコンポーネント: FallbackComponentプロパティにフォールバックUIコンポーネントを指定し、エラーをキャッチしたい子コンポーネント(この場合はMyComponent)をラップします。
  • onResetプロパティ: エラーがリセットされたときに実行される関数を指定します。例えば、フォームのリセットや再フェッチなどの処理をここに記述できます。

どんな場合にエラーになるの?

1. レンダリング中のエラー

Reactコンポーネントのrenderメソッドや関数コンポーネントの中でエラーが発生した場合です。例えば、以下のようなケースです:

function ProblematicComponent() {
  throw new Error('このコンポーネントはエラーをスローします!');
}

function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <ProblematicComponent />
    </ErrorBoundary>
  );
}

原因

  • 明示的にthrowでエラーを発生させている。
  • undefinednullに対して不正な操作を行った。

2. ライフサイクルメソッド内でのエラー

クラスコンポーネントのライフサイクルメソッド内でエラーが発生するケースです。

class ProblematicComponent extends React.Component {
  componentDidMount() {
    throw new Error('componentDidMount内でエラーが発生しました!');
  }

  render() {
    return <div>正常に動作しています。</div>;
  }
}

原因

  • componentDidMountcomponentDidUpdateで予期しないエラーが発生。
  • 外部APIからのレスポンスを処理する際のミス(例えば、空のデータに対して操作をしてしまう)。

3. サードパーティライブラリによるエラー

使用しているサードパーティライブラリ内でエラーが発生した場合もキャッチされます。

import ThirdPartyComponent from 'some-library';

function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <ThirdPartyComponent />
    </ErrorBoundary>
  );
}

原因

  • ライブラリのバグ。
  • ライブラリの使用方法を間違えた場合。

4. 非同期レンダリング中のエラー

非同期データをレンダリングする際、データが存在しない、または取得に失敗した場合。

function ProblematicComponent({ data }) {
  if (!data) {
    throw new Error('データが見つかりません!');
  }
  return <div>{data.name}</div>;
}

function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <ProblematicComponent data={null} />
    </ErrorBoundary>
  );
}

原因

  • 必要なデータがnullundefinedである。
  • 非同期処理中の状態を考慮せずにレンダリングしている。

5. フォールバックUIのエラー

ErrorBoundaryで指定したフォールバックUI自体がエラーを引き起こす場合。

function ErrorFallback({ error }) {
  // errorがない場合を考慮していない
  return <div>エラーが発生しました: {error.message}</div>;
}

原因

  • フォールバックUI内でerrorresetErrorBoundaryの扱いを間違えている。
  • フォールバックUIが他の依存コンポーネントを使っていて、その中でエラーが発生。

6. 手動でスローしたエラー

アプリケーション内で明示的にthrowを使ってエラーをスローする場合。

function MyComponent({ condition }) {
  if (!condition) {
    throw new Error('条件が満たされていません!');
  }
  return <div>正常に動作しています。</div>;
}

原因

  • 条件が満たされない場合にthrowを使って明示的にエラーを発生させた。
  • バリデーションや安全性チェックのためにエラーをスローする。

応用的な使い方

1. 特定のエラータイプに応じた処理

ErrorBoundaryは、発生したエラーの種類に応じて異なるフォールバックUIを表示することができます。

function ErrorFallback({ error, resetErrorBoundary }) {
  if (error instanceof SpecificError) {
    return (
      <div role="alert">
        <p>特定のエラーが発生しました:</p>
        <pre>{error.message}</pre>
        <button onClick={resetErrorBoundary}>再試行</button>
      </div>
    );
  }

  return (
    <div role="alert">
      <p>不明なエラーが発生しました:</p>
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>再試行</button>
    </div>
  );
}

2. ログ機能の追加

エラー発生時にログを記録することで、デバッグやモニタリングが容易になります。

function logErrorToService(error, info) {
  // エラー情報を外部サービスに送信する処理をここに記述
}

function App() {
  return (
    <ErrorBoundary
      FallbackComponent={ErrorFallback}
      onError={logErrorToService}
    >
      <MyComponent />
    </ErrorBoundary>
  );
}

3. 非同期エラーのハンドリング

react-error-boundaryは、非同期処理中に発生したエラーもキャッチできます。

import React, { useEffect } from 'react';
import { useErrorHandler } from 'react-error-boundary';

function MyComponent() {
  const handleError = useErrorHandler();

  useEffect(() => {
    async function fetchData() {
      try {
        // データ取得処理
      } catch (error) {
        handleError(error);
      }
    }

    fetchData();
  }, [handleError]);

  return <div>コンテンツ表示</div>;
}

まとめ

react-error-boundaryErrorBoundaryコンポーネントを使用することで、Reactアプリケーション内のエラーハンドリングがより簡単かつ強力になります。エラー発生時のユーザー体験を向上させるために、ぜひ活用してみてください。

公式ドキュメントはこちらからご覧いただけます。

関連する記事はこちら↓↓

タイトルとURLをコピーしました