イベントハンドラー内でのエラーをError Boundaryでキャッチする方法
Error Boundaryは、コンポーネント内でthrowされたエラーをキャッチする仕組み
Suspenseも似ていて、コンポーネント内でthrowされたPromiseをキャッチする仕組み
できた理由としては、エラーがキャッチされなかった場合に React コンポーネントツリー全体をunmountしたかったということがありそう。
この決定については議論がありましたが、我々の経験上、壊れた UI をそのまま表示しておくことは、完全に削除してしまうよりももっと悪いことです。例えば、Messenger のような製品において壊れた UI を表示したままにしておくと、誰かが誤って別の人にメッセージを送ってしまう可能性があります。同様に、支払いアプリで間違った金額を表示することは、何も表示しないよりも悪いことです。
一方でコンポーネント内でthrowされたエラーしかキャッチしないので、イベントハンドラー内で起きるエラーはキャッチできない
この点についてはReactのドキュメントでも触れられていて、イベントハンドラーで起きるエラーはその中でtry/catchしてほしいという雰囲気を感じる。
一方で、現実的にそれぞれのイベントハンドラーでtry/catch構文を追加させるのは大変で、エラーによって処理を分岐させるロジックも散らばってしまう傾向もある。できれば Error boundaries に、イベントハンドラーで生じるエラー処理周りも含めてエラー処理を集約させたい。
似たようなケースで、非同期処理のエラーに関してもError boudndaryはキャッチしない
非同期処理の中でエラーをcatchする方法は、対象のコンポーネントでuseStateのsetState関数を使えばいいとDanさんは言っている
上記のDanさんのアドバイスを応用したライブラリがあった
非同期処理やイベントハンドラ内でのエラーを扱うためのカスタムHooksを提供している
カスタムHooksの原理はとても単純でコードは以下の通り。非同期処理やイベントハンドラ内で起きたエラーをsetStateを使ってstate にセットし、stateがセットされたら再びhooks内でエラーをthrowする。
function useErrorHandler(givenError?: unknown): (error: unknown) => void {
const [error, setError] = React.useState<unknown>(null)
if (givenError != null) throw givenError
if (error != null) throw error
return setError
}
自分でも一応素振りしてみた