ShareDropにおけるフロントエンドエラーバウンダリの構築:コンポーネントレベルの例外キャッチと回復メカニズムの全解析

フロントエンドエラーハンドリングの重要性

WebRTCアプリケーションでは、ネットワーク状況の変化やデバイスの互換性、ユーザー操作の誤りが原因でエラーが発生する可能性があります。ShareDropでは、これらのエラーを段階的に処理する戦略を採用しており、特にコンポーネントレベルのエラーバウンダリがユーザー体験を保証する重要な防御層となっています。

エラーバウンダリの実装構造

Reactが提供するエラーバウンダリは、コンポーネントツリー内のJavaScriptエラーを捕捉し、代替UIを表示する仕組みです。ShareDropでは以下の要素で構成されています:

  • エラー状態の管理
  • エラー捕捉ロジック
  • 代替UIのレンダリング

基本的なエラーバウンダリ実装


class ComponentErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { errorStatus: false, exception: null };
  }

  static getDerivedStateFromError(exception) {
    return { errorStatus: true, exception };
  }

  componentDidCatch(exception, componentStack) {
    // エラーロギング処理
    errorLogger(exception, componentStack);
  }

  render() {
    if (this.state.errorStatus) {
      return this.props.fallback || <ErrorFallback exception={this.state.exception} />;
    }
    return this.props.children;
  }
}

ShareDropのエラーハンドリング実践

WebRTC接続やファイル転送の処理には特別なエラーハンドリングが必要です。以下の例は主要モジュールでの実装方法を示します。

WebRTC接続エラー処理


try {
  const connection = new RTCPeerConnection(config);
  // 接続処理ロジック
} catch (exception) {
  this.emit('connectionError', new Error('接続確立失敗: ' + exception.message));
}

ファイル転送エラー処理


async function sendFile(file, connection) {
  try {
    const channel = connection.createDataChannel('fileTransfer');
    // ファイル分割送信ロジック
  } catch (exception) {
    console.error('転送準備失敗:', exception);
    throw new Error('チャネル作成失敗: ' + exception.message);
  }
}

コンポーネントでのエラーバウンダリ適用

重要なUIコンポーネントにはエラーバウンダリを適用し、個別エラーによる全体障害を防止しています。

ペア接続コンポーネントの保護


const ProtectedPeerComponent = (props) => (
  <ComponentErrorBoundary fallback={<PeerErrorUI id={props.peerId} />}>
    <PeerComponent {...props} />
  </ComponentErrorBoundary>
);

ファイル転送コンポーネントの二重保護


class FileTransferArea extends React.Component {
  handleFileInput = (event) => {
    try {
      const selectedFiles = event.target.files;
      if (selectedFiles.length > 1) {
        this.props.onError(new Error('複数ファイル選択禁止'));
        return;
      }
      // ファイル処理ロジック
    } catch (exception) {
      this.props.onError(exception);
    }
  }
  
  render() {
    return <input type="file" onChange={this.handleFileInput} />;
  }
}

エラーロギングと監視


class ErrorMonitoring {
  recordException(exception, metadata) {
    if (process.env.NODE_ENV === 'production') {
      fetch('/api/log', {
        method: 'POST',
        body: JSON.stringify({
          message: exception.message,
          stackTrace: exception.stack,
          context: metadata,
          timestamp: new Date().toISOString()
        })
      });
    } else {
      console.error('エラー:', exception, 'メタデータ:', metadata);
    }
  }
}

カスタムエラーバウンダリの最適実装

  • ルートレベルで全体のエラーバウンダリを配置
  • 機能モジュールごとに個別のエラーバウンダリを適用
  • 動的ロードコンポーネント用の専用バウンダリを設計

回復可能なエラーバウンダリ実装例


class RetryableErrorBoundary extends ComponentErrorBoundary {
  state = {
    errorStatus: false,
    exception: null,
    retryable: false
  };

  componentDidCatch(exception, info) {
    super.componentDidCatch(exception, info);
    this.setState({
      retryable: exception.type !== '致命的エラー'
    });
  }

  executeRecovery = () => {
    this.setState({ errorStatus: false, exception: null });
    this.props.onRecovery && this.props.onRecovery();
  };

  renderCustomFallback() {
    return (
      <div className="例外表示">
        <h3>エラー発生</h3>
        <p>{this.state.exception?.message}</p>
        {this.state.retryable && (
          <button onClick={this.executeRecovery}>再試行</button>
        )}
      </div>
    );
  }
}

エラー分類とユーザーフィードバック

エラー種別に応じた対応策:

  • ネットワークエラー:再接続ボタン表示
  • ファイルエラー:フォーマット/サイズガイド表示
  • 権限エラー:設定手順の案内表示
  • 不明エラー:エラーレポート送信オプション提供

タグ: React WebRTC エラーハンドリング フロントエンド開発 ファイル共有

6月17日 20:45 投稿