「本番環境で真っ白な画面が出る」、これほどエンジニアの血の気が引く瞬間はありませんよね。
React開発において、コンポーネントのどこかで予期せぬ例外が発生したとき、Reactはデフォルトでツリー全体をアンマウントし、ブラウザを「真っ白」にしてしまいます。これを防ぐための最後の砦が、今回解説する「エラー境界(Error Boundaries)」です。
現場のシニアとして断言しますが、これを入れていないアプリケーションは「ブレーキのない車」と同じです。なぜ必要なのか、どう実装すべきか、そして現場での「泥臭い運用」までを紐解いていきましょう。
—
1. なぜ「クラスコンポーネント」なのか?
まず、中級者の方が最初に躓くポイントです。「なぜ今さらクラスコンポーネントを書くのか? Hooksで書けないのか?」という疑問ですね。
結論から言うと、Reactの現在の仕様では、エラー境界を実現するための `getDerivedStateFromError` と `componentDidCatch` という2つのライフサイクルメソッドは、クラスコンポーネントでしか提供されていません。
ReactチームもHooksでの実装を検討していますが、例外発生時のスタックトレース管理や、レンダリングのライフサイクルを制御する性質上、まだクラスコンポーネントの特権となっています。ここは「古い」と忌避せず、「アプリケーションの守護神」として割り切って実装しましょう。
—
2. 実務でそのまま使える!エラー境界のサンプルコード
まずは、コピペしてそのまま使える堅実な実装例を紹介します。ただエラーをキャッチするだけでなく、ロギング(Sentry等への送信)を想定した設計にしています。
import React, { Component, ErrorInfo, ReactNode } from ‘react’;
interface Props {
children: ReactNode;
fallback: ReactNode; // エラー時に表示するコンポーネント
}
interface State {
hasError: boolean;
}
export class ErrorBoundary extends Component
public state: State = {
hasError: false
};
// エラーが発生した際に状態を更新し、フォールバックUIを表示させる
public static getDerivedStateFromError(_: Error): State {
return { hasError: true };
}
// エラーの詳細をログ出力や監視ツール(Sentryなど)に送信する
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error(“ErrorBoundaryがエラーを検知しました:”, error, errorInfo);
// ここでAPI経由で監視サービスに通知を送るのがベストプラクティス
// logErrorToService(error, errorInfo);
}
public render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
使い方のポイント
単に `App.tsx` を囲むだけでは不十分です。「粒度」が重要になります。
全てのコンポーネントを囲むと管理コストが爆発します。例えば、「サイドバー」「メインコンテンツ」「ヘッダー」といった、機能単位で境界を設けるのが現場の鉄則です。
—
3. ブラウザとReactの裏側で起きていること
Reactの仮想DOMは、JavaScriptの例外が発生すると、そのコンポーネントのレンダリングプロセスが強制的に中断されます。もし境界がなければ、その例外が親へ親へと伝播し、最終的にDOMツリー全体を破棄する「React Unmount」が走ります。
エラー境界は、「これ以上上にエラーを伝播させないためのストッパー」です。例外をキャッチした瞬間、Reactはレンダリングを停止し、境界コンポーネントの `render` メソッドを呼び直して、あらかじめ定義しておいたフォールバックUIに切り替えます。
—
4. 現場で生き残るための「泥臭い」運用Tips
教科書には載っていない、実務レベルの知見を3つ伝授します。
1. エラーリセット機能を用意する
エラーが起きたまま画面が固まるのはUXとして最悪です。「再読み込みボタン」をフォールバックUIに配置し、ボタンクリック時に `this.setState({ hasError: false })` を呼び出すロジックを組み込みましょう。これだけでユーザーの離脱率が大きく変わります。
2. 「イベントハンドラ」のエラーはキャッチできないと知る
エラー境界は「レンダリング中のエラー」しかキャッチできません。ボタンクリックなどのイベントハンドラ内でのエラーは、別途 `try-catch` で処理する必要があります。これを混同して「動かない!」と悩む後輩を何度も見てきました。
3. 開発環境の「オーバーレイ」を過信しない
開発中にエラーが出ると真っ赤な画面(エラーオーバーレイ)が出ますが、あれはあくまで開発用の親切機能。本番環境では例外が発生しても黙り込むことが多いため、必ずプロダクションビルドでの動作確認を行ってください。
—
最後に:なぜ私たちがこれを実装するのか
フロントエンドエンジニアの仕事は、コードを書くだけではありません。「ユーザーが迷子にならないための安全網を張ること」です。
完璧なコードを書こうとするのは素晴らしいことですが、人間の書くコードには必ずバグが混入します。そのバグが致命的な体験(真っ白な画面)にならないように防波堤を築いておくことこそ、シニアエンジニアの矜持です。
まずは、あなたのプロジェクトの重要なコンポーネントを、今すぐ `ErrorBoundary` で囲むところから始めてみてください。その小さな一歩が、明日の夜、あなたの心を少しだけ穏やかにしてくれるはずです。

コメント