React Error Boundaryでグローバルエラーハンドリングを実現する方法

Reactアプリケーションの開発中に、予期しないエラーが発生することは避けられません。これらのエラーは、アプリの一部が正常に動作しない原因となり、最悪の場合、ユーザー体験を大きく損なう可能性があります。こうした問題を解決するために、ReactではError Boundaryという機能が提供されています。本記事では、Error Boundaryを用いてグローバルエラーハンドリングのパターンを確立し、エラー発生時にユーザー体験を維持しながら適切に対処する方法を詳しく解説します。Error Boundaryの基本概念から実装例、応用的な活用方法までを網羅し、Reactアプリケーションの安定性向上を目指します。

目次
  1. Error Boundaryとは?
    1. Error Boundaryの目的
    2. 動作の仕組み
    3. 適用例
  2. Error Boundaryの実装方法
    1. 基本的なError Boundaryの実装
    2. 使い方
    3. 説明
    4. 実装上の注意点
  3. Error Boundaryを用いたエラーキャッチの仕組み
    1. エラーキャッチの流れ
    2. コード例での動作説明
    3. エラー検知の仕組み
    4. エラーキャッチの利点
  4. Error Boundaryでのエラーロギング
    1. エラーロギングの重要性
    2. ロギングの実装方法
    3. ロギング関数の実装
    4. ロギングサービスの選定例
    5. エラーロギングのベストプラクティス
    6. 運用上の注意点
  5. グローバルエラーハンドリングのパターン
    1. グローバルエラーハンドリングの考え方
    2. Error Boundaryによるグローバルエラーハンドリング
    3. 複数レベルでのError Boundaryの利用
    4. エラー分類と処理方法
    5. エラーハンドリングのベストプラクティス
    6. 注意点
    7. グローバルエラーハンドリングの全体像
  6. Error Boundaryを使用する際の注意点
    1. Error Boundaryがキャッチできないエラー
    2. Error Boundaryの配置場所に関する注意
    3. フォールバックUIの設計
    4. テストとデバッグ
    5. パフォーマンスへの影響
    6. 注意点の総括
  7. Error Boundaryの拡張とカスタマイズ例
    1. 高度なカスタマイズの必要性
    2. カスタマイズ例 1: 動的なエラーメッセージの表示
    3. カスタマイズ例 2: 再試行機能の追加
    4. カスタマイズ例 3: 外部エラーロギングサービスとの連携強化
    5. カスタマイズ例 4: マルチエラー処理の対応
    6. カスタマイズのメリット
    7. 注意点
  8. 実践演習:Error Boundaryでのエラーキャッチ
    1. ケース1: 子コンポーネントで発生するエラーをキャッチする
    2. ケース2: 再試行可能なError Boundary
    3. ケース3: ロギングと通知の追加
    4. 実践ポイント
  9. まとめ

Error Boundaryとは?

Error Boundaryは、Reactコンポーネントの中で発生するJavaScriptエラーを検知し、UIのクラッシュを防ぐための特定のコンポーネントです。React 16以降で導入されたこの機能により、アプリ全体をクラッシュさせることなく、発生したエラーをキャッチして適切に処理できるようになりました。

Error Boundaryの目的

Error Boundaryは、以下のような目的で使用されます。

  • エラー検出:アプリ内で発生する予期しないエラーを特定。
  • UI保護:エラーが発生しても他の部分のUIが影響を受けないようにする。
  • エラーロギング:エラーの詳細をロギングサービスに送信してデバッグを容易にする。

動作の仕組み

Error Boundaryは、以下のライフサイクルメソッドを活用してエラーをキャッチします。

  • componentDidCatch(error, info): 子コンポーネントツリー内で発生したエラーとその情報をキャッチします。
  • getDerivedStateFromError(error): エラーが発生した場合の状態更新を行います。

適用例

Error Boundaryは、アプリ全体のどこにでも設置できますが、通常、以下のような場所に配置されます。

  • ページ単位:特定のページ全体のエラーをキャッチ。
  • ウィジェット単位:特定のコンポーネントやウィジェットだけを保護。
  • アプリ全体:アプリ全体のエラーを一括管理。

Error Boundaryを利用することで、アプリの安定性が大幅に向上し、ユーザーに安心感を提供することが可能です。

Error Boundaryの実装方法

ReactでError Boundaryを実装する手順を以下に解説します。Error Boundaryは通常のReactコンポーネントとして作成されますが、特定のライフサイクルメソッドを用いる点で特徴的です。

基本的なError Boundaryの実装

以下のコードは、シンプルなError Boundaryコンポーネントの例です。

import React, { Component } from 'react';

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

  static getDerivedStateFromError(error) {
    // エラーが発生したときの状態を更新
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // エラーログを外部サービスに送信するなどの処理を記述
    console.error('ErrorBoundary caught an error:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // エラー発生時のフォールバックUI
      return <h1>Something went wrong.</h1>;
    }
    // 正常時は子コンポーネントをレンダリング
    return this.props.children;
  }
}

export default ErrorBoundary;

使い方

Error Boundaryは、エラーをキャッチしたいコンポーネントをラップする形で使用します。

import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import MyComponent from './MyComponent';

function App() {
  return (
    <ErrorBoundary>
      <MyComponent />
    </ErrorBoundary>
  );
}

export default App;

説明

  • getDerivedStateFromError:
  • エラーが発生した際に、hasErrorの状態をtrueに更新します。
  • componentDidCatch:
  • エラーの詳細とエラーメッセージをキャッチします。
  • ログを送信したり、デバッグ情報を収集する場所として使用します。
  • render:
  • エラーが発生していればフォールバックUI(代替UI)を表示します。
  • 通常時はラップされた子コンポーネントをレンダリングします。

実装上の注意点

  • Error Boundaryは、イベントハンドラ内で発生したエラーや非同期エラーをキャッチしません。その場合は、try-catchやPromiseのエラーハンドリングが必要です。
  • フォールバックUIはユーザーにわかりやすいメッセージを提供することが望ましいです。

この基本的な実装をベースに、必要に応じてロギングやカスタマイズを追加することで、実用的なError Boundaryを構築できます。

Error Boundaryを用いたエラーキャッチの仕組み

Error Boundaryは、Reactアプリケーション内で発生する特定のエラーを検知し、それに応じた処理を行う仕組みを提供します。以下にError Boundaryのエラーキャッチの仕組みを詳しく解説します。

エラーキャッチの流れ

Error Boundaryは、子コンポーネントツリー内でエラーが発生した場合に動作します。その流れは次の通りです。

1. エラーの発生

子コンポーネント内で予期しないJavaScriptエラーが発生すると、通常はReactツリー全体がクラッシュします。しかし、Error Boundaryでラップされている場合、その範囲内でエラーをキャッチします。

2. 状態更新

Error Boundaryは、以下のライフサイクルメソッドを利用してエラーを処理します。

  • getDerivedStateFromError: エラーが発生した場合に、コンポーネントの状態を更新します。このメソッドは静的メソッドであり、副作用を持つ操作は含めるべきではありません。
  • componentDidCatch: エラーの詳細情報(errorerrorInfo)を取得し、副作用を伴う処理(ログ送信や通知など)を行います。

3. フォールバックUIのレンダリング

エラーが検知されると、Error Boundaryは通常のレンダリングを停止し、代わりにフォールバックUIを表示します。これにより、アプリ全体がクラッシュすることを防ぎます。

コード例での動作説明

以下のコード例で、Error Boundaryのエラーキャッチの動作を説明します。

class BuggyComponent extends React.Component {
  render() {
    // 意図的にエラーをスロー
    throw new Error('This is a test error');
  }
}

function App() {
  return (
    <ErrorBoundary>
      <BuggyComponent />
    </ErrorBoundary>
  );
}

上記コードを実行すると、BuggyComponentでスローされたエラーがError Boundaryにキャッチされ、フォールバックUIが表示されます。

エラー検知の仕組み

  • Error Boundaryの影響範囲:
  • 同じError Boundary内のすべての子コンポーネントが対象。
  • 別のError Boundaryでラップされたコンポーネントは独立して処理されます。
  • キャッチできないエラー:
  • イベントハンドラ内でのエラー。
  • 非同期関数内のエラー(例: async/await)。
  • サーバーサイドレンダリング(SSR)で発生するエラー。

エラーキャッチの利点

  • 安定性向上: 特定の部分でエラーが発生しても、他の部分が正常に動作し続けます。
  • デバッグ容易化: エラーログを収集することで、問題解決が迅速になります。
  • ユーザー体験の維持: ユーザーにわかりやすいフォールバックUIを表示することで、混乱を最小限に抑えます。

この仕組みにより、Reactアプリケーション全体のエラーハンドリングが強化され、開発者とユーザー双方にメリットをもたらします。

Error Boundaryでのエラーロギング

Error Boundaryは、Reactコンポーネント内で発生するエラーを検知するだけでなく、外部サービスやロギングシステムを使ってエラー情報を記録する仕組みを提供します。これにより、開発者はエラーの詳細を把握し、迅速に対処できるようになります。

エラーロギングの重要性

エラーをログとして記録することには次のような利点があります。

  • 問題の特定と修正の迅速化: エラーの発生場所や原因が明確になります。
  • 開発者への通知: 特定のサービスを使えば、リアルタイムでエラーを通知できます。
  • アプリの安定性向上: 蓄積されたエラーデータを分析して根本原因を解消することで、アプリの信頼性を高めます。

ロギングの実装方法

Error BoundaryのcomponentDidCatchメソッドを利用して、外部ロギングサービスにエラー情報を送信します。

以下のコードは、ロギングを実装したError Boundaryの例です。

import React, { Component } from 'react';
import logErrorToService from './logErrorToService'; // ロギング用の関数

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

  static getDerivedStateFromError(error) {
    // エラー発生時の状態を更新
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // エラーログを外部サービスに送信
    logErrorToService(error, errorInfo);
    console.error('Logged Error:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // エラー発生時のフォールバックUI
      return <h1>Something went wrong. Please try again later.</h1>;
    }
    return this.props.children;
  }
}

export default ErrorBoundary;

ロギング関数の実装

logErrorToService関数では、エラーを外部サービス(例: Sentry, LogRocket, Datadogなど)に送信します。

function logErrorToService(error, errorInfo) {
  // エラーデータをロギングサービスに送信
  fetch('https://logging-service.com/log', {
    method: 'POST',
    body: JSON.stringify({
      error: error.toString(),
      info: errorInfo.componentStack,
      timestamp: new Date().toISOString(),
    }),
    headers: {
      'Content-Type': 'application/json',
    },
  });
}

ロギングサービスの選定例

以下は、よく利用されるロギングサービスの例です。

  • Sentry: クライアントとサーバー両方でエラーを追跡可能。
  • LogRocket: ユーザーセッションの再現とエラー追跡を統合。
  • Datadog: 大規模な監視とアラート機能を提供。

エラーロギングのベストプラクティス

  • 詳細な情報を記録する: エラーメッセージだけでなく、コンポーネントスタックや発生時間を含む詳細をログに残す。
  • ユーザーへの通知を適切に行う: エラーを表示する際に、ユーザーの操作を妨げないよう工夫する。
  • データの保護: ユーザーデータが含まれる場合、セキュリティとプライバシーを確保する。

運用上の注意点

  • 過剰なログ送信はネットワーク負荷を増加させるため、重要なエラーに絞ってログを記録する。
  • 非公開APIキーや機密情報を含めないよう、適切にフィルタリングを行う。

Error Boundaryとエラーロギングを組み合わせることで、アプリケーションの監視体制を強化し、ユーザーに対して一貫した信頼性の高い体験を提供することが可能です。

グローバルエラーハンドリングのパターン

Error Boundaryを活用してReactアプリ全体で統一的なエラーハンドリングを構築することは、開発効率とユーザー体験の向上において非常に重要です。本セクションでは、グローバルエラーハンドリングのベストプラクティスを紹介します。

グローバルエラーハンドリングの考え方

グローバルエラーハンドリングとは、アプリケーション内で発生する全てのエラーを一元的に処理するパターンです。これにより、次の利点が得られます。

  • アプリ全体の一貫したエラー管理。
  • 重要なエラーのリアルタイム通知。
  • 障害発生時における迅速な対応。

Error Boundaryによるグローバルエラーハンドリング

Error Boundaryを利用して、グローバルエラーハンドリングを実現するには、アプリケーションの最上位レベルにError Boundaryを配置します。

import React from 'react';
import ReactDOM from 'react-dom';
import ErrorBoundary from './ErrorBoundary';
import App from './App';

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

複数レベルでのError Boundaryの利用

場合によっては、アプリ全体だけでなく、特定のセクションや機能に専用のError Boundaryを追加することで、エラーハンドリングの粒度を細かく制御できます。

function App() {
  return (
    <ErrorBoundary>
      <Header />
      <ErrorBoundary>
        <MainContent />
      </ErrorBoundary>
      <Footer />
    </ErrorBoundary>
  );
}

このようにすることで、例えばメインコンテンツでエラーが発生しても、ヘッダーやフッターは影響を受けません。

エラー分類と処理方法

エラーにはさまざまな種類があるため、分類して適切に処理することが重要です。

1. ユーザー入力エラー

  • : 必須フィールドの未入力、形式エラー。
  • 対策: ユーザーに具体的なフィードバックを提供。

2. 非同期通信エラー

  • : サーバーエラー、ネットワークタイムアウト。
  • 対策: リトライ機能の提供やエラーメッセージの表示。

3. 予期しないエラー

  • : 子コンポーネントのクラッシュ。
  • 対策: Error Boundaryを利用し、安全なフォールバックUIを表示。

エラーハンドリングのベストプラクティス

  • カスタムエラーメッセージを活用:
    ユーザーにわかりやすいメッセージを表示し、適切なアクションを促します。
  • ロギングと通知を組み合わせる:
    SentryやLogRocketのようなツールを使用して、重要なエラーを監視します。
  • リカバリ機能の提供:
    ユーザーが操作を続けられるよう、特定のエラーを無視して処理を再試行するオプションを用意します。

注意点

  1. Error Boundaryの適用範囲を明確にする:
    全体と部分的なエラーハンドリングを使い分けることで、適切なエラーレスポンスを提供します。
  2. 非同期エラーの別途処理:
    Error Boundaryは非同期エラーをキャッチしないため、API呼び出しやイベントハンドラではtry-catchを利用します。
  3. パフォーマンスを考慮:
    過剰なError Boundaryのネストはレンダリングパフォーマンスに影響を与える可能性があります。

グローバルエラーハンドリングの全体像

以下は、アプリ全体で統一的なエラーハンドリングを構築する手順の概要です。

  1. Error Boundaryを全体に適用
  2. セクションごとにError Boundaryを追加して詳細な制御を可能にする
  3. 外部ロギングサービスを利用してエラー情報を記録
  4. 非同期処理や入力エラーには個別のハンドリングを実装

これにより、アプリケーション全体で予測可能かつ効率的なエラーハンドリングを実現できます。

Error Boundaryを使用する際の注意点

Error BoundaryはReactアプリケーションでのエラーハンドリングに非常に便利ですが、その特性や制限を理解しないと、適切に機能しない場合があります。本セクションでは、Error Boundaryを使用する際の注意点について詳しく解説します。

Error Boundaryがキャッチできないエラー

Error Boundaryには、キャッチできるエラーとキャッチできないエラーがあります。以下にその違いを説明します。

キャッチできるエラー

  • 子コンポーネントツリー内でのランタイムエラー:
    例: レンダリング中のエラーやライフサイクルメソッド内でのエラー。

キャッチできないエラー

  • イベントハンドラでのエラー:
  function handleClick() {
    throw new Error("This error won't be caught by Error Boundary");
  }

解決策: try-catchを使用してイベントハンドラ内でエラーを処理します。

  • 非同期関数内でのエラー:
  async function fetchData() {
    throw new Error("This error won't be caught by Error Boundary");
  }

解決策: catchメソッドやtry-catchを利用して非同期エラーを処理します。

  • SSR(サーバーサイドレンダリング)中のエラー:
    サーバーサイドでレンダリングされるエラーはError Boundaryの対象外です。

Error Boundaryの配置場所に関する注意

Error Boundaryの適用範囲が適切でないと、エラーがアプリ全体に影響を及ぼす可能性があります。

全体に適用する場合

アプリ全体に適用するError Boundaryは、通常、アプリケーションの最上位(Appコンポーネント)に配置します。しかし、これだけでは各セクションの独立性を確保できません。

部分的に適用する場合

Error Boundaryを特定のセクションやコンポーネントに適用すると、その範囲でのエラーに限定して処理できます。これにより、他のセクションへの影響を最小限に抑えます。

<ErrorBoundary>
  <Header />
</ErrorBoundary>
<ErrorBoundary>
  <MainContent />
</ErrorBoundary>
<ErrorBoundary>
  <Footer />
</ErrorBoundary>

フォールバックUIの設計

Error Boundaryでは、エラー発生時にフォールバックUIを提供する必要があります。このUIは、ユーザー体験を損なわないように設計することが重要です。

フォールバックUIの注意点

  • 簡潔かつ説明的: エラー発生を簡潔に伝え、ユーザーが次に取るべきアクションを明示します。
  • 操作継続のサポート: エラー発生後もアプリ内の他の機能が利用可能であることを示します。

例:

if (this.state.hasError) {
  return (
    <div>
      <h1>Something went wrong.</h1>
      <button onClick={() => window.location.reload()}>Retry</button>
    </div>
  );
}

テストとデバッグ

Error Boundaryを正しく動作させるためには、適切なテストを行う必要があります。

テストのポイント

  • 正常系テスト: エラーが発生しない場合、子コンポーネントが正しくレンダリングされるか確認。
  • 異常系テスト: エラーが発生した場合、フォールバックUIが適切に表示されるか確認。

パフォーマンスへの影響

過剰にError Boundaryを配置すると、レンダリングパフォーマンスが低下する可能性があります。そのため、必要な箇所に限定して適用することが推奨されます。

注意点の総括

Error Boundaryを使用する際には、以下を守ることが重要です。

  1. キャッチできるエラーの範囲を理解する。
  2. 適切な範囲でError Boundaryを配置する。
  3. ユーザー体験を損なわないフォールバックUIを設計する。
  4. 非同期エラーやイベントハンドラ内のエラーには別途対応する。

Error Boundaryを適切に設計・配置することで、Reactアプリケーションの安定性とユーザー体験を大幅に向上させることができます。

Error Boundaryの拡張とカスタマイズ例

Error Boundaryは、標準的なエラー処理だけでなく、さまざまな要件に応じて拡張・カスタマイズすることが可能です。このセクションでは、実用的なカスタマイズ例とその実装方法を解説します。

高度なカスタマイズの必要性

アプリケーションの規模や用途に応じて、次のような高度なError Boundaryのカスタマイズが求められる場合があります。

  • 動的なエラーメッセージの表示: エラー内容に応じてフォールバックUIを変更。
  • エラーレポートの強化: 外部サービスとの連携を高度化。
  • ユーザー操作を促すUI: 再試行ボタンやサポートへのリンクを提供。

カスタマイズ例 1: 動的なエラーメッセージの表示

エラー内容に基づき、異なるフォールバックUIを表示する例です。

import React, { Component } from 'react';

class CustomErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, errorInfo) {
    console.error('Error caught:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      if (this.state.error.message.includes('Network')) {
        return <h1>Network error. Please check your connection.</h1>;
      }
      return <h1>An unexpected error occurred. Please try again.</h1>;
    }
    return this.props.children;
  }
}

export default CustomErrorBoundary;

カスタマイズ例 2: 再試行機能の追加

エラーが発生した際に再試行ボタンを表示し、再レンダリングをトリガーする例です。

import React, { Component } from 'react';

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

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  handleRetry = () => {
    this.setState({ hasError: false });
  };

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h1>Something went wrong.</h1>
          <button onClick={this.handleRetry}>Retry</button>
        </div>
      );
    }
    return this.props.children;
  }
}

export default RetryErrorBoundary;

カスタマイズ例 3: 外部エラーロギングサービスとの連携強化

Error Boundaryを外部サービス(例: SentryやLogRocket)と統合し、詳細なエラーレポートを送信する例です。

import React, { Component } from 'react';
import * as Sentry from '@sentry/react'; // Sentryを使用する場合

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

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    Sentry.captureException(error, { extra: errorInfo });
    console.error('Error reported to Sentry:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong. Our team has been notified.</h1>;
    }
    return this.props.children;
  }
}

export default LoggingErrorBoundary;

カスタマイズ例 4: マルチエラー処理の対応

複数のError Boundaryを動的に生成し、異なるエラーを個別に処理する仕組みを実装します。

function MultiErrorBoundary({ children, errorTypes }) {
  return errorTypes.map((ErrorBoundary, index) => (
    <ErrorBoundary key={index}>{children}</ErrorBoundary>
  ));
}

使用例:

<MultiErrorBoundary errorTypes={[CustomErrorBoundary, RetryErrorBoundary]}>
  <MainComponent />
</MultiErrorBoundary>

カスタマイズのメリット

  1. 柔軟性の向上: アプリの要件に応じてError Boundaryを最適化できます。
  2. ユーザー体験の強化: フォールバックUIを細かくカスタマイズすることで、ユーザーに親切なエラーメッセージを提供できます。
  3. エラーデータの活用: 詳細なログを収集することで、エラーの原因分析と再発防止が可能になります。

注意点

  • 過剰なカスタマイズはコードの複雑化につながるため、必要最小限にとどめます。
  • 外部サービスとの連携では、機密情報が含まれないようデータを適切に管理します。

これらのカスタマイズ例を参考に、Error Boundaryを効率的かつ効果的に活用しましょう。

実践演習:Error Boundaryでのエラーキャッチ

Error Boundaryの実践的な活用方法を学ぶために、具体的なシナリオを通じてその動作を確認します。このセクションでは、以下のケースを取り上げ、コード例を交えて解説します。

ケース1: 子コンポーネントで発生するエラーをキャッチする

Error Boundaryを使用して、子コンポーネント内のエラーをキャッチする基本的なケースを実装します。

import React, { Component } from 'react';

// ErrorBoundaryの実装
class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    console.error('Caught an error:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong. Please reload the page.</h1>;
    }
    return this.props.children;
  }
}

// エラーを発生させるコンポーネント
function BuggyComponent() {
  throw new Error('This is a test error');
}

// アプリケーション
function App() {
  return (
    <ErrorBoundary>
      <BuggyComponent />
    </ErrorBoundary>
  );
}

export default App;

動作確認

  • BuggyComponentでエラーがスローされます。
  • Error Boundaryがエラーをキャッチし、フォールバックUIが表示されます。

ケース2: 再試行可能なError Boundary

エラー発生後に再試行ボタンを追加し、コンポーネントの再レンダリングをトリガーします。

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

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  handleRetry = () => {
    this.setState({ hasError: false });
  };

  componentDidCatch(error, errorInfo) {
    console.error('Error caught:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h1>An error occurred.</h1>
          <button onClick={this.handleRetry}>Retry</button>
        </div>
      );
    }
    return this.props.children;
  }
}

// BuggyComponentでエラーが発生する例
function App() {
  const [triggerError, setTriggerError] = React.useState(false);

  return (
    <RetryErrorBoundary>
      <button onClick={() => setTriggerError(true)}>Trigger Error</button>
      {triggerError && <BuggyComponent />}
    </RetryErrorBoundary>
  );
}

動作確認

  • Trigger ErrorボタンをクリックするとBuggyComponentでエラーがスローされます。
  • エラー発生後、フォールバックUIとRetryボタンが表示されます。
  • Retryをクリックすると再試行が行われ、状態がリセットされます。

ケース3: ロギングと通知の追加

外部ロギングサービスにエラー情報を送信し、開発チームが迅速に問題を把握できるようにします。

import * as Sentry from '@sentry/react';

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

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    Sentry.captureException(error, { extra: errorInfo });
    console.error('Logged Error to Sentry:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h1>An unexpected error occurred. Our team has been notified.</h1>;
    }
    return this.props.children;
  }
}

動作確認

  • エラーが発生すると、Sentryにエラー情報が送信されます。
  • フォールバックUIが表示され、エラー通知が明示されます。

実践ポイント

  1. エラーハンドリングの確認: フォールバックUIが正しく表示されるか確認します。
  2. 再試行の有効性: 状態リセットが適切に動作し、再試行可能であるかを確認します。
  3. ロギングの検証: 外部サービスにエラー情報が正確に送信されるか確認します。

これらの実践演習を通じて、Error Boundaryの仕組みを深く理解し、さまざまなエラーハンドリングシナリオに対応できる力を養いましょう。

まとめ

本記事では、ReactのError Boundaryを活用したグローバルエラーハンドリングの実践的な方法を詳しく解説しました。Error Boundaryの基本的な仕組みから実装方法、カスタマイズ、実践的な演習までを網羅し、アプリケーションの安定性とユーザー体験の向上を目指しました。

Error Boundaryは、Reactアプリケーションで発生する予期しないエラーを検知し、UI全体のクラッシュを防ぎます。また、再試行ボタンの追加や外部ロギングサービスとの連携など、用途に応じた柔軟なカスタマイズが可能です。

適切なエラーハンドリングは、開発効率を高めるだけでなく、ユーザーに安心感を与えます。この記事を参考に、Error Boundaryを活用して堅牢なReactアプリケーションを構築してください。

コメント

コメントする

目次
  1. Error Boundaryとは?
    1. Error Boundaryの目的
    2. 動作の仕組み
    3. 適用例
  2. Error Boundaryの実装方法
    1. 基本的なError Boundaryの実装
    2. 使い方
    3. 説明
    4. 実装上の注意点
  3. Error Boundaryを用いたエラーキャッチの仕組み
    1. エラーキャッチの流れ
    2. コード例での動作説明
    3. エラー検知の仕組み
    4. エラーキャッチの利点
  4. Error Boundaryでのエラーロギング
    1. エラーロギングの重要性
    2. ロギングの実装方法
    3. ロギング関数の実装
    4. ロギングサービスの選定例
    5. エラーロギングのベストプラクティス
    6. 運用上の注意点
  5. グローバルエラーハンドリングのパターン
    1. グローバルエラーハンドリングの考え方
    2. Error Boundaryによるグローバルエラーハンドリング
    3. 複数レベルでのError Boundaryの利用
    4. エラー分類と処理方法
    5. エラーハンドリングのベストプラクティス
    6. 注意点
    7. グローバルエラーハンドリングの全体像
  6. Error Boundaryを使用する際の注意点
    1. Error Boundaryがキャッチできないエラー
    2. Error Boundaryの配置場所に関する注意
    3. フォールバックUIの設計
    4. テストとデバッグ
    5. パフォーマンスへの影響
    6. 注意点の総括
  7. Error Boundaryの拡張とカスタマイズ例
    1. 高度なカスタマイズの必要性
    2. カスタマイズ例 1: 動的なエラーメッセージの表示
    3. カスタマイズ例 2: 再試行機能の追加
    4. カスタマイズ例 3: 外部エラーロギングサービスとの連携強化
    5. カスタマイズ例 4: マルチエラー処理の対応
    6. カスタマイズのメリット
    7. 注意点
  8. 実践演習:Error Boundaryでのエラーキャッチ
    1. ケース1: 子コンポーネントで発生するエラーをキャッチする
    2. ケース2: 再試行可能なError Boundary
    3. ケース3: ロギングと通知の追加
    4. 実践ポイント
  9. まとめ