Webプログラミング

React+axios+Material UIでスピナーとメッセージを表示する

今回はReact + Material UIで通信中にスピナーを表示し、通信終了時にメッセージを表示するプログラムを作成します。非同期通信にはaxiosを利用します。

 

こちらの記事でReact Hook Formを利用してフォームを作成したので、そのプログラムを使います。

React Hook Formがいい感じ!

Contentsはじめに使ってみるMaterial UIと使うまとめ はじめに ReactでWebアプリケーションを作る際に自力でフォームを作成するのは、現実的に考えるとやらない方がいいです。自力でフ ...

続きを見る

完成図はこちら↓↓

はじめに

完成したコードはGitHubから取得して下さい。

ソースコードの説明
src/components/PostContainer.js スピナーとメッセージの状態管理
src/components/PostForm.js フォームの描画とそのsubmit処理
src/components/PostLayout.js 全体のレイアウト
src/Utils/SnackBar.js メッセージのコンポーネント
src/Utils/ErrorButton.js エラーメッセージを確認するためのダミーボタン

普通にやるとAPI通信は成功するので、エラーハンドリングの確認用にダミーボタンを用意してあります。

APIの通信先

今回はAPIの通信先としてJSONPlaceholderのAPIを使います。ダミーAPIを提供しているサイトです。

このサイトでは様々なリソースがあり、記事やコメント、写真、todoなどを想定したAPIを提供しています。

https://jsonplaceholder.typicode.com/postsにGETメソッドでアクセスすれば記事一覧がJSONで取得できますし、POSTメソッドを送れば201ステータスのレスポンス(+データなど諸々)が帰ってきます。

今回はスピナーとメッセージを表示することが目的であるため、リソースはなんでもいいのですが"/posts"を使用します。

axiosのセットアップ

今回はaxiosで複雑な処理はしませんが、以下のようにinstanceを生成しています。instanceを生成して有効に使う方法は今後紹介予定です。

import axios from "axios";

const instance = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/"
});

export default instance;

使う際は上記のファイルをimportして通常のaxiosと同じように使うだけです。

補足

baseURLを指定しているとアクセスのたびにget("https://jsonplaceholder.typicode.com/posts")とする必要はなく、get("posts")とするだけでよくなります。

スピナーを作成

通信中にスピナーを表示させます。Material UIのBackdropCircularProgressを使用します。Backdropは画面全体に表示する半透明のパネル(?)的なものです。

まずスピナー+Backdropの状態管理をするために以下のように設定します。

const [progress, setProgress] = useState(false);

デフォルトをfalseにしておき、submitボタンが押されたときにtrueにします。

あとは変数を作り、progressがtrueであればスピナーを、progressがfalseであればフォームを表示する処理を書きます。

/* 通信中であれば、formを非表示にし、スピナーを表示する */
let form = (
  <Backdrop className={classes.backdrop} open={progress}>
    <CircularProgress color="inherit" />
  </Backdrop>
);
if (!progress) {
  form = <PostForm setProgress={setProgress} setStatus={setStatus} />;
}

これをreturnメソッド内で{form}のように表示させます。

メッセージを表示

次に通信が成功したのか、失敗したのかを表示する仕組みを作っていきます。

ここではMaterial UIのSnackBarを使います。公式ドキュメントから不要な箇所を削り、色やテキストの部分を変数化しています。

import React from "react";
import Snackbar from "@material-ui/core/Snackbar";
import MuiAlert from "@material-ui/lab/Alert";

function Alert(props) {
  return <MuiAlert elevation={6} variant="filled" {...props} />;
}

const CustomizedSnackbars = props => {
  const { open, handleClose, type, message } = props;

  return (
    <Snackbar open={open} autoHideDuration={3000} onClose={handleClose}>
      <Alert onClose={handleClose} severity={type}>
        {message}
      </Alert>
    </Snackbar>
  );
};

export default CustomizedSnackbars;

このSnackBarの状態管理は以下のように設定しました。

ポイント

今回はスピナー、メッセージの状態をuseStateを使って管理していますが、プログラムの様々な箇所で使うものですのでReduxのstoreやReactのContextで管理したほうが便利です。

/* SnackBarの状態管理(ReduxやContextでやる方がいい) */
const [status, setStatus] = React.useState({
  open: false,
  type: "success",
  message: "成功しました。"
});
const handleClose = (event, reason) => {
  if (reason === "clickaway") {
    return;
  }
  setStatus({ ...status, open: false });
};

コンポーネントを配置する際は以下のようにopen,handleClose,type,messageを指定します。

typeはsuccess, info, warning, errorの中から指定します。

// PostContainer.js
<React.Fragment>
  <PostLayout>
    {form}
    <ErrorButton setStatus={setStatus} />
  </PostLayout>
  <SnackBar
    open={status.open}
    handleClose={handleClose}
    type={status.type}
    message={status.message}
  />
</React.Fragment>

これで準備は出来ました。あとは通信をするときに呼び出すだけです。

onSubmitにて通信前にスピナーを表示、成功か失敗かによってメッセージを表示、最後にスピナーを消します。

// Submitボタンを押したときの処理
const onSubmit = data => {
  console.log(data); // 送信するデータ
  setProgress(true); // スピナーを表示
  axios
    .post("posts", data)
    .then(response => {
      console.log(response);
      // 成功のメッセージを表示
      setStatus({
        open: true,
        type: "success",
        message: "データの作成に成功しました。"
      });
    })
    .catch(error => {
      console.log(error);
      // エラーハンドリング
      if (error.response) {
        setStatus({
          open: true,
          type: "error",
          message: `失敗しました。(コード:${error.response.status})`
        });
      }
    })
    .then(() => {
      // 常に実行される
      setProgress(false);  // スピナーを消す
    });
};

これで完成です。そのままだとAPIが全て成功してしまうので、エラーハンドリングの確認用にボタンを用意しました。

押すと以下のようにエラーメッセージとエラーコードが表示されます。

以上です。

まとめ

今回はReact + Material UIで通信中にスピナーを表示し、通信終了時にメッセージを表示するプログラムを作りました。

いたって単純ですが、よく使うプログラムなのでぜひご活用下さい。

 

この記事は参考になりましたか?

下記のボタンよりアンケートにご協力お願いします。

-Webプログラミング
-,

© 2020 エンジニアの本棚