グローバルナビゲーションへ

本文へ

フッターへ

お役立ち情報Blog



Reactのerror boundaryでキャッチされないエラーをキャッチできるようにする

Reactのerror boundary

error boundary は自身の子コンポーネントツリーで発生した JavaScript エラーをキャッチし、エラーを記録し、クラッシュしたコンポーネントツリーの代わりにフォールバック用の UI を表示する React コンポーネントです。error boundary は配下のツリー全体のレンダー中、ライフサイクルメソッド内、およびコンストラクタ内で発生したエラーをキャッチします。Error Boundary―React

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

今回試していませんが、error boundaryをシンプルで再利用可能なラッパーを提供しているライブラリも存在するようです。

2022年3月の時点では、関数コンポーネントのerror boundaryはサポートされていないので、クラスコンポーネントで記述します。

基本的な使い方はerror boundaryを作成して、以下のようにエラーをキャッチしたいコンポーネントをラップする形です。
こうすることでErrorBoundaryコンポーネントでラップした子コンポーネントで発生したエラーをキャッチしてくれるようになります。

ただし公式ドキュメントにも記載されている通り、全てのエラーをキャッチしてくれるわけではありません。

error boundaryがキャッチしないエラー

error boundary は以下のエラーをキャッチしません

  • イベントハンドラ(詳細
  • 非同期コード(例:setTimeout や requestAnimationFrame のコールバック)
  • サーバサイドレンダリング
  • (子コンポーネントではなく)error boundary 自身がスローしたエラー
Error Boundary―React

非同期コードで発生したエラーをキャッチできないのは困るので、error boundaryでもエラーをキャッチできるようにした方法がGitHubのissueに載っています。

これでerror boundaryでも非同期コードで発生したエラーを補足できるようになりました。めでたしめでたし。

と言いたいところですが、大抵のWebアプリケーションではREST APIやGraphQLなどのWeb APIを叩くような非同期コードを実行することが多いです。 毎回適切にエラー処理が出来ていればいいのですが、エラー処理のし忘れやエラーを握りつぶしてしまうこともあります。人間だもの。

できることなら復旧可能なエラー以外は直ちにアプリケーションをクラッシュさせてエラー画面を表示したい、つまりerror boundaryでエラーをキャッチしたいのが心情です。 そこで探してみると別の方法が同じissueと辿ったissueで紹介されていました。

これで非同期コードで発生したエラーをerror boundaryでキャッチできるようになりました。

Window: unhandledrejection イベント

 unhandledrejection  イベントとは何ぞやということで調べました。

ステータスがrejectedのPromiseが誰にもキャッチされなかった時に、JavaScriptエンジンがグローバルエラーを生成し、 そのイベント名が  unhandledrejection  のようです。

error boundaryでWindowオブジェクトの  unhandlerejection  イベントを購読することで非同期コードで発生したエラーに対応しているんですね。

では、そもそもなぜerror boundaryは非同期コードのエラーをキャッチできないのでしょうか。

その謎を解明するべく、我々はアマゾンの奥地へと向かった。

error boundary が非同期コードをキャッチできない理由

色々と調べると素晴らしい記事を見つけました。

ざっくり理解した要約:

  1. Promiseのexecutorでエラーが発生すると、暗黙的にエラーをPromise.rejectとして扱う(Promise.rejectでエラーをラップする)[1
  2. error boundaryは同期コードのエラーはキャッチできるが、Promise.rejectでラップされたエラーはawait(Promise.catch)で待ち受けていないので、エラーとしてではなくステータスがrejectedのPromiseとして扱われてcatchブロックをすり抜ける [2
  3. 結果、error boundaryで非同期コードをキャッチできない

unhandledrejectionに対応したerror boundary

最後に  unhandledrejection  に対応したerror boundaryを再掲します。

まとめ

ここでerror boundaryがキャッチしないエラーを再掲します。

error boundary は以下のエラーをキャッチしません

  • イベントハンドラ(詳細
  • 非同期コード(例:setTimeout や requestAnimationFrame のコールバック)
  • サーバサイドレンダリング
  • (子コンポーネントではなく)error boundary 自身がスローしたエラー
Error Boundary―React

今回は上記の非同期コードをキャッチできるようにする方法について調査しました。

イベントハンドラで発生したエラーについてはあまり調査ができていません。

GitHubにずばりなタイトル Why are Error Boundaries not triggered for event handlers? のissueを見つけましたのでリンクを貼っておきます。 経緯について興味がある方は調べてみてください。

本記事の執筆で自分が非同期 async/await(Promise)について何も理解していないことを痛感しました。

私は雰囲気で非同期コードを書いていた。

The following two tabs change content below.

美髭公

ソリューション事業部 システムエンジニア
2013年にアーティスに入社。システムエンジニアとしてアーティスCMSを使用したWebサイトや受託システムの構築・保守に携わる。環境構築が好き。
この記事のカテゴリ

FOLLOW US

最新の情報をお届けします