ErrorBoundary
はReact内でruntimeエラーが起こった際に、エラーをキャッチし、あらかじめ設定しておいたFallback UIを表示するための仕組みをもつコンポーネントのことを指します。React16で導入されました。
例えば、下記のようにコンポーネント内のレンダリングフェーズでエラーが投げられた場合、
ErrorBoundaryがエラーをキャッチして、 hoge
ではなくfallbackである fuga
を表示します。
ErrorBoundaryで囲っていない場合、画面がクラッシュしてしまいます。
export default function App() { throw new Error() return <div>hoge</div> } <ErrorBoundary fallbackRender={<div>fuga</div>}> <App /> </ErrorBoundary>
このとき落とし穴だったのが、ErrorBoundaryはイベントハンドラ内でthrowされたエラーはキャッチしない ということです。
明示されているのは旧バージョンのドキュメントですが、下記のように書かれています。
error boundary は以下のエラーをキャッチしません:
そもそも、イベントハンドラ内でエラーがthrowされ、ハンドリング内でcatchできていなかったとしても、レンダリングフェーズでのエラーと違いアプリケーション画面はクラッシュしません。
ユーザーのアクションによって起こったエラーであることがほとんどなので、ユーザーにエラー理由を伝えるようなフィードバックをしたいですね。
レアケースではあるかもしれませんが、 イベントハンドラから ErrorBoundary
にエラーを伝搬させる方法もあるのでご紹介します。
react-error-boundary で簡単に実装できます。
下記のように useErrorBoundary
から呼び出した showBoundary
の引数にエラーを渡して実行することで、イベントハンドラーからエラーの伝播を行うことができます。
import { useErrorBoundary } from "react-error-boundary"; export default function App() { const { showBoundary } = useErrorBoundary(); const clickCatchHandler = useCallback(() => { showBoundary(new Error()); }, []); return ( <div> <button onClick={clickCatchHandler}>キャッチできるエラー</button> </div> ); }
ライブラリ内の処理を見ると、内部的に error状態を監視するstateを切り替えることでレンダリングフェーズでのエラーを引き起こしてくれています。
(はてなブログはgistじゃないとコード展開してくれないのか 🤔)
下記で動作を確認することができます。