【Next.js】ローディング画面を表示処理の実装例

今回は、クライアント側で処理中などをユーザにわかるようにするためのローディング画面(ぐるぐる回るアイコンなど)を表示する実装方法の例を紹介していきます。

ローディング画面を表示するための状態を管理するライブラリに「Recoil」を使用しています。

スポンサーリンク

検証環境

検証に使用した環境/ライブラリを次に記載します。

  • React
    • バージョン:18.2.0
  • Next.js
    • バージョン:12.1.6
  • Recoil
    • バージョン:0.7.4

動作例

ローディング画面を表示する動作例は、次のサイトで確認することができます。

CodeSandbox SSE Discontinued

プロジェクト情報

実装例で紹介しているプログラム内容などの詳細については、次のサイトで確認することができます。

https://codesandbox.io/s/next-js-typescript-recoil-loading-j5sk73

プログラム内容

ローディングコンポーネント

【src/components/loading.tsx】

ローディング処理に関するコンポーネントの全体ソースコードは、次のようになります。

import { atom } from "recoil";
import { useRecoilState, useRecoilValue } from "recoil";

type LoadingTyep = {
  loading: boolean;
};

const loadingState = atom<LoadingTyep>({
  key: "loadingState",
  default: {
    loading: false
  }
});

export const useLoading = () => {
  const [state, setState] = useRecoilState<LoadingTyep>(loadingState);
  const start = () => {
    setState({ ...state, ...{ loading: true } });
  };
  const stop = () => {
    setState({ ...state, ...{ loading: false } });
  };
  return { start, stop };
};

export const Loading = () => {
  const state = useRecoilValue<LoadingTyep>(loadingState);
  if (!state.loading) {
    return <></>;
  }
  return (
    <div>
      <img src="images/loading.gif" alt="loading" />
      <div>Loding...</div>
    </div>
  );
};
export default Loading;

ローディングの状態を管理するための定義は、次の箇所になります。

type LoadingTyep = {
  loading: boolean;
};

const loadingState = atom<LoadingTyep>({
  key: "loadingState",
  default: {
    loading: false
  }
});

表示状態は、boolean型のloadingという名前で管理しています。

ローディングの状態を変更するための処理は、次の箇所になります。

export const useLoading = () => {
  const [state, setState] = useRecoilState<LoadingTyep>(loadingState);
  const start = () => {
    setState({ ...state, ...{ loading: true } });
  };
  const stop = () => {
    setState({ ...state, ...{ loading: false } });
  };
  return { start, stop };
};

start関数は、ローディング表示を開始状態に変更しています。stop関数は、ローディング表示を終了状態に変更しています。

ローディングの表示をするための処理は、次の箇所になります。

export const Loading = () => {
  const state = useRecoilValue<LoadingTyep>(loadingState);
  if (!state.loading) {
    return <></>;
  }
  return (
    <div>
      <img src="images/loading.gif" alt="loading" />
      <div>Loding...</div>
    </div>
  );
};
export default Loading;

表示状態を取得するための処理は、const state = useRecoilValue<LoadingTyep>(loadingState)の箇所になります。

state.loadingを使用してローディングの表示有無の判定をしています。ローディング表示は、任意の表示処理に変更することもできます。実装例では、画像を表示する処理になっています。

APPコンポーネント

【src/pages/_app.tsx】

APPコンポーネントの全体ソースコードは、次のようになります。

import type { AppProps } from "next/app";
import { RecoilRoot } from "recoil";
import Loading from "../components/loading";

function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <RecoilRoot>
        <div>Next.js + TypeScript + Recoil</div>
        <div>Loading Example.</div>
        <Loading />
        <Component {...pageProps} />
      </RecoilRoot>
    </>
  );
}
export default App;

Recoilを使用するためRecoilRootタグで全体を括る必要があります。ローディング表示するためLoadingコンポーネントも指定しています。

画面表示

【src/pages/index.tsx】

画面を表示するための全体のソースコードは、次のようになります。

import type { NextPage } from "next";
import { useLoading } from "../components/loading";

const Index: NextPage = () => {
  const { start, stop } = useLoading();

  return (
    <div>
      <div>
        <button type="button" onClick={start}>
          <span>Start</span>
        </button>
        <button type="button" onClick={stop}>
          <span>Stop</span>
        </button>
      </div>
    </div>
  );
};

export default Index;

ローディングの状態を変更するための関数の取得処理は、const { start, stop } = useLoading()の箇所になります。ローディングコンポーネントのstart関数とstop関数を使用できるようになります。

実装例では、ボタン押下のonClickイベントのタイミングでローディング表示の状態を変更することにより、表示制御をしている処理になります。

まとめ

Recoilを使用したローディング表示をするための実装例を紹介しました。