最も単純な ErrorBoundary コンポーネントをカプセル化して、React 例外を処理する

最も単純な ErrorBoundary コンポーネントをカプセル化して、React 例外を処理する

序文

React 16から、子コンポーネントで発生したエラーを捕捉し、エラーログを記録し、ダウングレードコンテンツを表示できるエラー境界の概念が導入されました。具体的な公式ウェブサイトのアドレスは

エラー境界は、コンポーネント エラーによってページ全体が使用不能になり、画面が空白になるのを防ぎます。エラー境界は、グレースフル デグラデーションを使用して代替 UI を提示します。エラー境界は、レンダリング中、ライフサイクル中、およびコンポーネント ツリー全体のコンストラクター内でエラーをキャプチャできます。 React 16 以降では、エラー境界でキャッチされないエラーが発生すると、React コンポーネント ツリー全体がアンマウントされます。

エラー境界の意味

  • 一部のUIがクラッシュしますが、Webアプリ全体がクラッシュするわけではありません

ページを閲覧しているときに、バックエンドから返される例外やフロントエンドでのエラーチェックが原因で、ユーザーエクスペリエンスが悪くなることがあります。妻と一緒に電車に座って鍋を食べながら歌を歌っていると、突然盗賊に襲われ、エラーメッセージが表示されることを想像してみてください。金額を設定するときや重要なページを表示するときなど、一部のシナリオでは、エクスペリエンスが非常に悪くなります。たとえば、ゲームで500をチャージしましたが、インターフェイスの理由により、チャージNaNが表示されます。この表示は、表示されないよりも迷惑です。ただし、JS例外キャプチャは誰もがよく知っていると思いますので、ビジネスコードのtry-catchパッケージで十分です。ただし、コンポーネントで例外をキャプチャするには、React が提供するError Boundary機能を使用し、 componentDidCatchフックを使用してページ例外をキャプチャして、例外がページ全体に広がらないようにし、ページに空白の画面が表示されるのを効果的に防ぐ必要があります。

公式サイトの実装方法

👉 クラス コンポーネントが 2 つのライフサイクル メソッド static getDerivedStateFromError() または componentDidCatch() のいずれか (または両方) を定義すると、エラー境界になります。エラーがスローされたら、static getDerivedStateFromError() を使用して代替 UI をレンダリングし、componentDidCatch() を使用してエラー メッセージを出力します 👈

ErrorBoundaryクラスはReact.Componentを拡張します。
  コンストラクタ(props) {
    スーパー(小道具);
    this.state = {hasError: false };
  }
  静的 getDerivedStateFromError(エラー) {
    // 次のレンダリングで劣化した UI を表示できるように状態を更新します
    {hasError: true } を返します。
  }
  コンポーネントDidCatch(エラー、エラー情報) {
    // エラー ログをサーバーに報告することもできます logErrorToMyService(error, errorInfo);
  }
  与える() {
    if (this.state.hasError) {
      // ダウングレードされた UI をカスタマイズしてレンダリングできます。 return <h1>Something went wrong.</h1>;
    }
    this.props.children を返します。
  }
}

その後、通常のコンポーネントとして使用できます。

<エラー境界>
  <マイウィジェット />
</エラー境界>

エラー境界は JavaScript のcatch {}同様に機能しますが、 Reactコンポーネントにのみ適用される点が異なります。 classコンポーネントのみがエラー境界コンポーネントになることができます。ほとんどの場合、エラー境界コンポーネントを一度宣言して、アプリケーション全体で使用すれば十分です。これを使用すると、ラップされたコンポーネント内のエラーやthrow new Error()によってスローされた例外がエラー境界コンポーネントによってキャッチされ、フォールバック UI として表示されます。

設定可能なErrorBoundaryをカプセル化します

公式サイトがエラー境界コンポーネントをどのように実装しているかを理解した後、 return <h1>Something went wrong</h1>直接記述する代わりに、 ErrorBoundaryコンポーネントをカプセル化して便利なホイールを作成できます。 react-reduxの原則を学んだ後、高階コンポーネントを使用してreactコンポーネントをラップし、データとメソッドをstoreにグローバルに挿入できることがわかりました。同様に、高階コンポーネントを使用して、エラーをキャプチャできる react コンポーネントにラップすることもできます。

1. 設定可能なErrorBoundaryクラスコンポーネントを作成する

公式サイトのErrorBoundaryと比較すると、パラメータを受け入れることで、ログの報告方法と表示されるUI動的に設定できます。受信UIについては、 reactコンポーネントまたはReact Elementとして受け入れられるように設定できます。また、コンポーネントを通じてパラメータを渡すことができるため、基礎となる UI で特定のエラー情報を取得できます。

  • componentDidCatch(): エラーログ処理用のフック関数
  • static getDerivedStateFromError() : スローされたエラーをパラメータとして受け取り、状態を更新するための値を返します。
ErrorBoundaryクラスはReact.Componentを拡張します。
  状態 = { エラー: false };
  静的 getDerivedStateFromError(エラー) {
    {エラー}を返します。
  }
  コンポーネントDidCatch(エラー、エラー情報) {
    エラーが発生した場合
      // レポート ログは、親コンポーネントによって挿入された関数を通じて実行されます。this.props.onError(error, errorInfo.componentStack);
    }
  }
  与える() {
    const { フォールバック、 FallbackComponent } = this.props;
    const { error } = this.state;
    if (エラー) {
      const fallbackProps = {エラー};
      //React要素かどうかを判定する
      React.isValidElement(フォールバック)の場合{
        フォールバックを返します。
      }
      //コンポーネントメソッド if (FallbackComponent) {
        <FallbackComponent {...fallbackProps} /> を返します。
      }
      throw new Error("ErrorBoundary コンポーネントをフォールバック UI に渡す必要があります");
    }
    this.props.children を返します。
  }
}

この方法では、基盤となるUI表示と錯誤日志動的に取得できるため、コンポーネントの柔軟性が向上します。ただし、別の問題もあります。サーバーが突然 503 または 502 で失敗し、フロントエンドが応答を取得できなくなる場合があります。このとき、コンポーネントはエラーを報告しますが、しばらくすると正常に戻ります。より良い方法は、ユーザーがErrorBoundaryによってカプセル化されたコンポーネント内のメソッドをクリックして、ページを更新せずにエラー コンポーネントを再読み込みすることです。この時点で、カバーする必要があるコンポーネントは、 ErrorBoundary処理するメソッドを公開する必要があります。

1. ErrorBoundary に、挿入されたリセット メソッドがあるかどうかを検出するメソッドを追加します。リセット メソッドがある場合は、それを実行し、エラー状態をリセットしてエラー状態を false にします。

リセットエラー境界 = () => {
  this.props.onReset() の場合、 this.props.onReset() になります。
  this.setState({ エラー: false });
};

2. レンダリング用に render に関数コンポーネント タイプを追加します。リセット メソッドとエラー情報は、処理のために現在のコンポーネントにパラメータとして渡すことができます。

 与える() {
    const { fallback、 FallbackComponent、 fallbackRender } = this.props;
    const { error } = this.state;
    if (エラー) {
      const フォールバックプロパティ = {
        エラー、
        リセットエラー境界: this.resetErrorBoundary、
      };
      ...
      fallbackRender の typeof === "function") の場合は fallbackRender(fallbackProps) を返します。
      ...
    }
    this.props.children を返します。
  }

2. ErrorBoundaryを高階関数でラップして返す

「react」からReactをインポートします。
「./core」からDefaultErrorBoundaryをインポートします。
const catchreacterror = (境界 = DefaultErrorBoundary) => 内部コンポーネント => {
  プロパティを返す => (
    <境界 {...props}>
      <InnerComponent {...props} />
    </境界>
  );
};

使用とテスト

クリックして増加するデモでは、数値が特定の値に達すると例外がスローされます。ここでは、クラス コンポーネントと Function コンポーネントが例外を開始するコンポーネントとしてテストされます。

  • 例外を引き起こしたコンポーネント
//関数コンポーネント const fnCount1 = ({ count }) => {
  if (count == 3) throw new Error("count is three");
  <span>{count}</span> を返します。
};
//クラスコンポーネント class fnCount2 extends React.Component {
  与える() {
    const { count } = this.props;
    if (count == 2) throw new Error("count is two");
    <span>{count}</span> を返します。
  }
}
  • エラー例外を処理するための関数コンポーネント
const errorbackfn = ({ エラー: { メッセージ }, resetErrorBoundary }) => (
  <div>
    <p>問題が発生しました</p>
    <pre>{メッセージ}</pre>
    <button onClick={resetErrorBoundary}>もう一度お試しください</button>
  </div>
);
  • エラー例外を処理するための共通コンポーネント
const errorbackcom = () => <h1>エラーが発生しました。元に戻すことはできません</h1>;
  • テストコンポーネント
//例外を開始したコンポーネントをラップし、エラー編集を処理できる高階コンポーネントを返します。const SafeCount1 = catchreacterror()(fnCount1);
const SafeCount2 = catchreacterror()(fnCount2);
//メインコンポーネントをテストする const App = () => {
  定数[count, setCount] = useState(0);
  const ListenError = (arg, info) => console.log("Error: " + arg.message, info); //エラーが発生したときのコールバック const onReset = () => setCount(0); //リセットがクリックされたときのコールバック return (
    <div className="アプリ">
      <セクション>
        <button onClick={() => setCount(count => count + 1)}>+</button>
        <button onClick={() => setCount(count => count - 1)}>-</button>
      </セクション>
      <時間 />
      <div>
        クラスコンポーネント:
        <セーフカウント2
          カウント={count}
          フォールバックレンダリング={errorbackfn}
          onReset={onReset}
          onError={ListenError}
        />
      </div>
      <div>
        機能コンポーネント:
        <セーフカウント1
          カウント={count}
          フォールバックコンポーネント={errorbackcom}
          onError={ListenError}
        />
      </div>
    </div>
  );
}; 

ミッション完了!

発生した問題とその概要

反応エラー境界が万能ではない場合が多々あります。例えば、

  • イベントエラー

上記の例では、this.o が存在しないため、エラーが報告されます。Window.onerror はこれをキャプチャできますが、エラー境界はキャプチャできません。

  • 非同期コード

サーバーサイドレンダリングとエラー境界自体

要約する

  • コンポーネントを抽出✔
  • バグレポート✔
  • UI 抽象化 ✔
  • エラーリセット✔
  • アンフックモード ✖
  • サーバー ✖

ここまで、この記事を読んでいただきありがとうございます。お役に立てれば幸いです。React のエラー境界について大まかに理解し、簡単なErrorBoundaryただし、最適化できるポイントはまだたくさんあります。ご不明な点がありましたら、お気軽にご指摘ください。 ErrorBoundary と react の詳細については、123WORDPRESS.COM の他の関連記事にも注目してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • React でのポータルとエラー境界処理の実装
  • Reactエラー境界コンポーネント処理
  • React 16における例外処理の詳細な説明
  • Reactワークフローとエラー境界の実装プロセスの説明

<<:  MySQL 8.0.3 RCがリリースされようとしています。変更点を見てみましょう。

>>:  MySQL データベース内の同じテーブルを同時にクエリして更新する方法

推薦する

DockerはGitを使用してJenkinsのリリースとテストプロジェクトの詳細なプロセスを実装します

目次1. Dockerをインストールする2. カスタムネットワークアドレスを作成する3. Docke...

Docker の NFS-Ganesha イメージを使用して NFS サーバーを構築する詳細なプロセス

目次1. NFS-Ganeshaの紹介2. NFS-Ganeshaの設定3. NFS-Ganesha...

JS でカルーセル効果を実現する 3 つの簡単な方法

この記事では、JSカルーセル効果の具体的なコードを実現するための3つの方法を紹介します。具体的な内容...

Linux での UDP について学ぶ

目次1. UDPとLinuxの基礎の紹介2. 各機能の使い方1. ソケット機能の使用2. バインド機...

Mac に mysql5.7 をインストールするための完全な手順 (画像とテキスト付き)

最近、Mac システムを使用して、ローカル Web サーバー環境を構築する準備をしていました。 Ma...

node.jsのインストールとHbuilderXの設定の詳細な説明

npm インストールチュートリアル: 1. Node.jsインストールパッケージをダウンロードする公...

Docker プルタイムアウトの解決策

最近、Docker イメージのプルが非常に不安定です。遅く、タイムアウトすることがよくあります。 x...

js を使用して年カルーセル選択効果をネイティブに実装する例

序文js を使用して、年の回転選択効果を実現します。では早速、写真を見てみましょう。 1. アイデア...

MySQL データ定義言語 DDL の基本ステートメント

MySQL DDL ステートメントDDL、DMLとは何ですか。 DDL はデータ定義言語であり、CR...

Dockerは同じIPネットワークセグメントとの接続を実現する

最近、Docker とホストが同じネットワーク セグメント上で通信する問題を解決し、そのプロセス全体...

SQL でテーブルにフィールドとコメントを追加する方法

1. フィールドを追加します。 alter table テーブル名 ADD フィールド名 タイプ;例...

MySQLデータベースとテーブルシャーディングの概要

プロジェクトの開発中に、データベースのデータがどんどん大きくなり、その結果、1 つのテーブルにデータ...

Vue は PC カメラを呼び出してリアルタイムで写真を撮る機能を実装します

VueはPCカメラを呼び出してリアルタイムで写真を撮影します。参考までに、具体的な内容は次のとおりで...

vue-cli の紹介とインストール

目次1. はじめに2. vue-cli の紹介2.1 コマンドライン2.2 CLI サービス2.3 ...

高性能な HTML アプリケーションを作成するためのヒント

Web ページのパフォーマンスを向上させるにはどうすればよいでしょうか?ほとんどの開発者は、Java...