エラーハンドリング:ErrorBoundary【React】

Reaactエラーハンドリング 標準のErrorBoundaryとreact-error-boundaryについて
◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
VSCode Dev Containersで楽々開発環境構築祭り〜Python/Reactなどなど〜
Visual Studio Codeの拡張機能であるDev Containersを使ってReactとかPythonとかSpring Bootとかの開発環境をラクチンで構築する方法を紹介するイベントです。
https://tech-lab.connpass.com/event/311864/

今回は、Reactでのエラーハンドリングの方法について調べてまとめました。標準のErrorBoundaryとライブラリであるreact-error-boundaryを使用した方法について解説します。標準のErrorBoundaryの問題点をreact-error-boundaryでは克服しているようです。

初めに

どもども~先週の遅れを爆速で取り戻している龍ちゃんです。先週はぬるっと四連休があったこともあり頭がぼーっとしていましたね。今週の僕は待ちと技術検証の時間だったので心に余裕がある状態で、作業に没頭しています。

Reactでのエラーハンドリングの方法についての第何弾かわかりませんね。エラーハンドリングの方法に関して言えば、あらゆるパターンの方法が存在しています。今回は、標準のエラーハンドリングとライブラリ【react-error-boundary】を使用したエラーハンドリングを紹介します。バージョンが4に上がってから、書き方が変わりました!!ここはバージョン3までの書き方です!。

それでは初めて行きます。

標準のエラーハンドリング

こちらはReactの公式ページに乗っています。React16以降では、エラーが発生した場合コンポーネントがアンマウントされて真っ白な画面が表示されます。デバック時は開発者ツールを使えばエラーがのぞけますが、デプロイ後にエラーが発生した際に何も表示されなければ問い合わせが殺到もしくはすっとブラウザバックされてしまいますね。エラーっぽくてちょっと良い感じのエラー画面を表示されたらうれしいですよね。

標準のエラーハンドリングの問題点

エラーハンドリングするための意図は上記で示した通りです。ですが、標準のエラーハンドリングでは取得できないエラーがあります。こちらは公式サイトにもでかでかと乗っています。

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

意外とこの制限困りますね。イベントハンドラと非同期コードのエラーが捕まらないのがなかなか困ります。

この制限があるので標準のエラーハンドリングだけだと苦しいものがあったりします。回避する方法ももちろんあるのですが、とりあえず構築の方法について説明します。

コーディング

コーディングの方法について説明していきます。static getDerivedStateFromError

componentDidCatchをどちらか一方もしくは両方を設定することでエラーハンドリングになります。


import React, { ErrorInfo } from 'react';

export default class ErrorBoundary extends React.Component<
  { children: React.ReactNode },
  { hasError: boolean; errorMessage: string }
> {
  constructor(props: { children: React.ReactNode }) {
    super(props);
    this.state = { hasError: false, errorMessage: '' };
  }

  static getDerivedStateFromError(error: Error) {
    // ここでエラーを受け取る
    // ここでStateの変更を行って処理を振り分けたりする。
    return { hasError: true, errorMessage: error.message };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    // ログに通知したりする部分
    console.error(error, errorInfo);
  }

  render() {
    const btnClick = () => {
      window.location.reload();
    };
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return (
        <>
          Something went wrong.{this.state.errorMessage}
          
        </>
      );
    }
    return this.props.children;
  }
}

componentDidCatchはエラー情報をログに書き込んだりする処理を行います。static getDerivedStateFromErrorではエラーを取得したら変数を書き換える処理を行います。取得するstateで定義をしておけば、メッセージだけでなく情報を追加で送信することができます。

とりあえず、先ほど説明を入れたように標準のエラーハンドリングでは取得できない問題があります。それを解決するための手法としてライブラリ【react-error-boundary】を使用する方法があります。

使い方としては、こちらのような使い方になります。

<ErrorBoundary>
  <ErrorPage />
</ErrorBoundary>

react-error-boundary

こちらのライブラリでは、標準のエラーハンドリングでは対応できないエラーに対応することができるようになっているようです。勉強に利用したサイトを下に列挙しておきます。

とりあえず、めちゃめちゃわかりやすい参考サイトがあったので置いています。こちらのサイトでもわかるように解説したいと思います。

セットアップ

とりあえず、セットアップをしていきましょう。バージョンが4に上がってから、書き方が変わりました!!ここはバージョン3までの書き方です!。

yarn add react-error-boundary

ライブラリはこちらでインストールが終了します。

コーディング

コーディングの基本的な使用方法としては以下になります。


import { ErrorBoundary, FallbackProps } from 'react-error-boundary';

export const ErrorBoundaryPage = () => {
  return (
    <>
      <ErrorBoundary FallbackComponent={ErrorFallback} onError={onError}>
        <ErrorPage />
      </ErrorBoundary>
    </>
  );
};

const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => {
  return (
    <>
      <pre>react-error-boundary {error.message}</pre>
      <button type="button" onClick={resetErrorBoundary}>
        reset button
      </button>
    </>
  );
};

const onError = (error: Error, info: { componentStack: string }) => {
  console.error(error, info);
};

ライブラリで取得したErrorBoundary コンポーネントでコンポーネントを挟むことで標準のエラーハンドリングと同等の処理を挟むことができます。標準のエラーハンドリングではrenderでレンダリングを変更していましたが、こちらの場合はFallbackComponentにコンポーネントを指定することで表示が切り替わります。しかも、resetErrorBoundaryを処理するとエラー画面から自動で復帰します。onErrorではエラー情報を取得してログに記録する部分を記述します。

標準のエラーハンドリング問題点解消方法

標準のエラーハンドリングでは取得できないエラーを解消するためにエラーを伝搬する機能が【react-error-boundary】には用意されています。その代わり明示的にエラーを通知する必要があります。以下のフックを用いてエラーを通知します。

import { useErrorBoundary } from 'react-error-boundary';
const { showBoundary } = useErrorBoundary();
showBoundary(new Error('error'));

try~catchを使用してエラーが発生したタイミングでuseErrorBoundaryから取得した関数で通知する必要があります。こちらを使用することで、イベントハンドラ中や非同期コードの処理中にエラーが発生した場合に無事エラーを通知することができます。

終わりに

お疲れ様です。今回はReactでのエラーハンドリングについて言及していきました。まだ、非同期コードのエラーをキャッチすることはできません。非同期通信でAxiosを使っている場合は、こちらの記事の【Axios Interseptor】と今回の【react-error-boundary】組み合わせで非同期コードのエラーハンドリングを行うことができそうです。次回のブログはそちらの記事でまとめていきます。

ではでは~またね~

 

アバター画像
About 龍:Ryu 106 Articles
2022年入社で主にフロントエンドの業務でTailwindと遊ぶ日々。お酒とうまいご飯が好きで、運動がちょっと嫌いなエンジニアです。しゃべれるエンジニアを目指しておしゃべりとブログ執筆に注力中(業務もね)//
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

1人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる