React SPAでネットワークが落ちているときにエラー画面表示

React:SPA時のネットワークエラー画面遷移
◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

今回は、React SPAでファイルを取得後にネットワークがオフラインになった場合にネットワークエラーページに遷移させるプログラムについて解説しました。データフェッチのタイミングでも同等のことができますが、今回はJS既存のイベントリスナーを使用して実装しています。

ご挨拶

ども!ブログネタのためにアプリを開発を始めたら、ブログの執筆する時間が捻出できなくなっている龍ちゃんです。ペース配分が難しいですね。

さて、今回は社内で定期開催されている「輪読会」で得た知見を発信する内容となります。今回取り扱う内容としては、「React SPAでサイトを覗いている際に、ネットワークが落ちたらエラー画面を表示する」となっています。実際に執筆していて「必要か?」ってなっていましたが、知らなかったのでまとめておきます。

それでは、さっくりと初めて行きましょう。

SPAとネットワークエラー

Single Page Application(SPA)の特徴では、以下の特徴があります。こちらの記事で、SSR・SSG・SPAの違いを図解で解説されています(超優良参考資料)。

SPAの特徴

SPAの面白いところは、表示に関するCSSやJSファイルはサーバーから一括で受け取り、クライアント側でAPIにアクセスを行いデータを取得して描画します。サーバーとの通信時にネットワークエラーが発生した場合、表示に関するデータごと取得できないのでクライアント側でネットワークエラーが表示されます。

ですが、サーバー側からのデータ取得時はオンラインで、その後オフラインになった場合では表示はあるけどエラーが吐きだされます。以下の赤枠部分ですね。

SPAの問題点

このエラーハンドリングに関しては、axiosでも実装することができます。今回は、ブラウザの標準の機能を使って実装してみようと思います。もし、データ通信部分でaxiosを使用している場合は、データ通信に関するエラーになりますので、一元管理することが開発としてもいいかもしれません。実際は、サーバーとAPIサーバーからのデータの取得は感知することができないくらい、早く通信が発生すると思います。そういった点でも、axiosにまとめるほうがいいですね。

実装

構成としては、react-error-boundaryを実装します。参考資料としては、こちらを参照してください。構成に必要なファイルとしては、以下になります。

  • ネットワークエラーをハンドリングするためのError:NetworkError
  • react-error-boundary用のファイル:ErrorBoundaryComponent
  • ネットワークイベント用リスナー:NetworkStatusConfig

各項目解説していきます。

ネットワーク用エラー

まずは、Errorを継承したネットワークエラーを作成します。既存のエラーを拡張して作成することで、エラー発生時の切り分けを行うことができます。

export class NetWorkError extends Error {
  constructor() {
    super('network error');
    this.name = 'NetWorkError';
  }
}

react-error-boundary用のファイル

こちらでは、エラーが起きた際に画面の差し替えを行ってくれます。先ほど、拡張したエラーと送信されてきたエラーを比べてネットワークエラーを判別しています。

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

import { NetWorkError } from './Error/NetworkError';

type Props = {
  children: React.ReactNode;
};
export const ErrorBoundaryComponent = (props: Props) => {
  const { children } = props;

  return <ErrorBoundary FallbackComponent={ErrorFallback}>{children}</ErrorBoundary>;
};

const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => {
  if (error instanceof NetWorkError) return <div>ネットワークエラー</div>;
  return (
    <>
      <button className="" onClick={resetErrorBoundary}>
        リトライ
      </button>
    </>
  );
};

ネットワークイベント用リスナー

最後に、ネットワークイベント「オフライン」を監視するコンポーネントを作成します。ネットワークの監視イベントは、イベントハンドラーを用いて監視します。エラーが発生した場合は、先ほど作成したネットワーク用エラーをreact-error-boundaryのカスタムフックでエラーを伝搬させています(const { showBoundary } = useErrorBoundary();)。

import { useEffect } from 'react';
import { useErrorBoundary } from 'react-error-boundary';

import { NetWorkError } from './Error/NetworkError';

type Props = {
  children: React.ReactNode;
};

export const NetworkStatusConfig = (props: Props) => {
  const { children } = props;
  const { showBoundary } = useErrorBoundary();
  const throwNetworkError = () => {
    showBoundary(new NetWorkError());
  };

  useEffect(() => {
    window.addEventListener('offline', throwNetworkError);
    return () => {
      window.removeEventListener('offline', throwNetworkError);
    };
  });

  return <>{children}</>;
};

全体構成

それぞれ設定したコンポーネントを作成します。ネットワークイベント監視内で、react-error-boundaryのカスタムフックを使用して、エラーイベントを伝搬させているため、react-error-boundaryのコンポーネントの中に、ネットワークイベント監視用コンポーネントを設定する必要があります。

import { ErrorBoundaryComponent } from './ErrorBoundary';
import { NetworkStatusConfig } from './NetworkStatusConfig';

type Props = {
  children: React.ReactNode;
};

export const UtilitiesConfig = (props: Props) => {
  const { children } = props;
  return (
    <>
      <ErrorBoundaryComponent>
        <NetworkStatusConfig>
            {children}
        </NetworkStatusConfig>
      </ErrorBoundaryComponent>
    </>
  );
};

確認

せっかく実装したので、確認をしていきたいと思います。オフライン状態を自発的に起こすには、Googleの開発者ツールを使用しましょう。

「F12」を押して、ネットワークタブを開きましょう。以下の画面を参考にドロップリストを開いてください。

こちらでは、ネットワークの状態をデフォルトで「高速」「低速」「オフライン」の3つを意図的に発生させることができます。こちらで、SPAの特殊な状態を意図的に発生させることができますね。

おわりに

ども!まったく知見のないところから、仕入れることができたので成長を感じれました。実際の要件で必要になるかはわかりませんが、知らなくてできないのと、知ってるけどやらないは大きく違うので、良い勉強です。

今回参考にした書籍は、「フロントエンド開発入門 プロフェッショナルな開発ツールと設計・実装」になります。月に一度は、技術書を読んでいきたいですね。

ではまた!

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

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

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


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



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

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる