【React】リクエストの状態によってラベルが変わるボタン

## はじめに
　本記事は、プログラミング初学者、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## リクエストの状態によってラベルが変わるボタン

```postFuga.js
import axios from "axios";

export const postOrder = (params) => {
  const DEFAULT_API_LOCALHOST = 'http://localhost:3001/api/v1'
  const fuga = `${DEFAULT_API_LOCALHOST}/fuga`

  return axios.post(fuga,
    {
      hoge: params.hoge
    },
  )
  .then(res => {
    return res.data
  })
  .catch((e) => console.error(e))
}

```

```constants.js
export const REQUEST_STATE = {
  INITIAL: 'INITIAL',
  LOADING: 'LOADING',
  OK: 'OK',
}
```


```hogeReducer.js
import { REQUEST_STATE } from "./constants";

export const initialState = {
  postState: REQUEST_STATE.INITIAL,  // リクエストの状態
  Hoge: null,  // postするデータ                      
};

export const actionTypes = {
  POSTING: 'POSTING',
  POST_SUCCESS: 'POST_SUCCESS',
}

export const hogeReducer =  (state, action) => {
  switch (action.type) {
    // postStateをREQUEST_STATE.LOADINGに変更
    case actionTypes.POSTING:
      return {
        ...state,
        postState: REQUEST_STATE.LOADING,
      };
    // postStateをREQUEST_STATE.OKに変更
    case actionTypes.POST_SUCCESS:
      return {
        ...state,
        postState: REQUEST_STATE.OK,
      };
    default:
      throw new Error();
  }
}
```

```App.jsx
import './App.css';
import React, { useState } from 'react';
import styled from 'styled-components';
import { SubmitButton } from './SubmitButton.jsx';
import { initialState, actionTypes, hogeReducer } from './hogeReducer';
import { postFuga } from './postFuga'

export const SubmitButton = styled.button`
  width: 300px;
  background-color: black;
  color: white;
  border-style: none;
  padding: 8px 16px;
  font-size: 16px;
  cursor: pointer;
  :hover {
    opacity: 0.7;
  }
  :focus {
    outline: 0;
  }
`;

function App() {
  const [state, dispatch] = useReducer(HogeReducer, initialState);

  const postHoge = () => {
    // HogeReducerのcase actionTypes.POSTING:を実行
    dispatch({ type: actionTypes.POSTING });
    // postFugaを実行（リクエストを実行）
    postFuga({
      hoge: state.hoge,
    }).then(() => {
      // HogeReducerのcase actionTypes.POST_SUCCESS:を実行
      dispatch({ type: actionTypes.POST_SUCCESS });
    });
  };

  const submitButtonLabel = () => {
    // postStateによってボタンのラベルを変更する
    switch (state.postState) {
      // postHoge内のdispatch({ type: actionTypes.POSTING });が実行され、HogeReducerのcase actionTypes.POSTING:の処理が完了し、postStateがREQUEST_STATE.LOADING:になっている間は「送信中...」を表示
      case REQUEST_STATE.LOADING:
        return "送信中...";
      // postHoge内のthenの処理が完了し、HogeReducerのcase actionTypes.POST_SUCCESS:が実行され、postStateがREQUEST_STATE.OKになると「送信が完了しました」を表示
      case REQUEST_STATE.OK:
        return "送信が完了しました";
      // クリック前には「送信」を表示
      default:
        return "送信";
    }
  };

  return (
    <SubmitButton
      // ボタンをクリックするとpostHogeが実行される
      onClick={() => postHoge()}
      // 処理中や成功した場合にはボタンをdisabledにする
      disabled={state.postState === REQUEST_STATE.LOADING || state.postState === REQUEST_STATE.OK}
    >
      {submitButtonLabel()}
    </SubmitButton>
  );
}

export default App;

```