2022-03-09
2022-3-9
ライブラリを使用して、Error Boundaryを実装。react-error-boundary
frontend,
React.js,
Library,
TypeScript,
仕事も決まって、モチベーションが高い今日この頃です。
今回はreact-error-boundaryを使用して、エラー発生時の処理を実装していきます。
Error-boundaryとは
Reactのドキュメントから
error boundary は自身の子コンポーネントツリーで発生した JavaScript エラーをキャッチし、エラーを記録し、クラッシュしたコンポーネントツリーの代わりにフォールバック用の UI を表示する React コンポーネントです。
なぜ必要か? 一部のコンポーネント内でエラーが発生した時に、全てのUIが崩れるのはユーザー体験として良くないです。 それにReactの醍醐味の一つがコンポーネントによる疎結合化です。せっかく役割ごとに分割したのあれば、エラーもその範囲内で処理するべきです。
react-error-boundary
react-error-boundary
はError-boundaryを実装できるライブラリです。
Reactの公式ドキュメントによるError-boundaryの実装はいまだにクラスコンポーネントを使用して実装されています(2022/3)。今から新しく開発するプロジェクトなら、可読性を落とさないためにも、クラスコンポーネントの使用はなるべく避けたいですね。 そんな時に、react-error-boundaryを使用してエラーが発生する可能性のあるコンポーネントをラッピングすることで、error-boundaryを実装することができます。また、ロギング機能も提供しております。
実装
何はともあれインストール
yarn add react-error-boundary
Fallback用コンポーネントの作成
エラー発生時にフォールバックし、対応させるためのコンポーネントを作成します。 今回は、ErrorContainerというコンポーネントを作成します(スタイルは、tailwind.css使用しています)。
import type { VFC } from "react"; import type { FallbackProps } from "react-error-boundary"; export const ErrorContainer: VFC<FallbackProps> = (props) => { return ( <div role="alert" className="mx-auto mt-8 mb-20 w-96 font-vollkorn text-center text-gray-600" > <h2 className="my-12 font-caveat text-4xl font-bold sm:text-5xl"> ERROR. </h2> <h4 className="text-sm sm:text-base"> エラーが発生しました。申し訳ございませんが、しばらくしてから再度お試しください。 </h4> <pre className="my-2 text-sm sm:text-base"> <span>Something went wrong:</span> {props.error.message} </pre> <button className="hover:underline text-lg text-blue-400" onClick={props.resetErrorBoundary} > Retry </button> </div> ); };
propsにはreact-error-boundaryが持っているfallbackPropsを使用します。
fallbackPropsのinterface
interface FallbackProps { error: Error; resetErrorBoundary: (...args: Array<unknown>) => void; }
error.messageでエラー内容の表示、resetErrorBoundaryメソッドは、発火するとエラー状態がリセットされ、onResetメソッドと組み合わせて再トライ処理を実装することができます。
コンポーネントをラッピング
Layout.tsxなど、親階層のコンポーネント内で配下のコンポーネントをラッピングします。FallbackComponentの値に作成したErrorContainerを指定します。
親階層のコンポーネント
import type { FC, ReactNode } from "react"; import { ErrorBoundary } from "react-error-boundary"; type Props = { children: ReactNode; }; export const Layout: FC<Props> = (props) => { return ( <> <header>ヘッダー</header> <ErrorBoundary FallbackComponent={ErrorContainer} onReset={() => console.log(“エラー状態をリセットさせる処理”}> <div>{props.children}</div> </ErrorBoundary> <footer>フッター</footer> </> ); };
children内のどこかで、エラーを発生させてみます。
throw new Error()
ヘッダー、フッター、ともに表示されていますね。
簡単にError boundaryを実装することができました。
ラッピングする箇所は、最上位のコンポーネントじゃなくてもいいので、場合によってはページごとに処理を切り替えることもできます。是非、実装してみてください。
ブログにも実装
自分のブログでも実装。 個人ブログなのでほとんど自己満足になりますが、いい感じに作れました。
ローディングページの実装(余談)
余談ですが、react-error-boundaryの実装と同時にLoading時のページも実装しました。
ブログの取得だけなんで、ローティング時間は微々たるものですが、せっかくなので作成しました。