ReactのRedux内でaxiosを使用した通信をする

# はじめに
[前々回のReactを使用してWeb画面を作成する](https://qiita.com/mink0212/items/a53b285dd26f57b835b3)では、reactの簡単なサンプルと共に説明をまとめました。
[前回のReduxとReduxToolkitを使用してReact内でデータを管理する](https://qiita.com/mink0212/items/add733e2a2a1dfbc3aed)では、reduxのの簡単なサンプルと共に説明をまとめました。
今回はaxiosを使用してREST APIから情報を取得して画面に表示させるサンプルと説明をまとめようと思います。

# 環境
 - node.js: v12.18.2
 - webpack: 4.44.1
 - React: 16.13.1
 - Redux: 7.2.1
 - axios: 0.19.2

# 環境作成
[前回のReactを使用してWeb画面を作成する](https://qiita.com/mink0212/items/a53b285dd26f57b835b3)と[前回のReduxとReduxToolkitを使用してReact内でデータを管理する](https://qiita.com/mink0212/items/add733e2a2a1dfbc3aed)の続きとなります。
環境構築などはそちらを見てください。

## axios
REST APIへ通信するためにaxiosというライブラリを使用します。

### axiosのインストール

```

npm install axios
```

## Redux Thunk
axiosは非同期で通信を実行します。しかし、Reduxは非同期の処理をするのは若干手間です。それらを楽にするためにRedux Thunkというミドルウェアを使用します。

### Redux Thunkのインストール

```

npm install redux-thunk
```

## Babel/polyfill
axiosを使用するにあたってpolyfillが必要になります。

### Babel/polyfillのインストール

```

npm install @babel/polyfill --save-dev
```

# Reactでaxiosを使用する
## Reactのソースの作成
[前回のReduxとReduxToolkitを使用してReact内でデータを管理する](https://qiita.com/mink0212/items/add733e2a2a1dfbc3aed)の続きなので、ソースも前回のに対して変更していく形にします。

### sliceファイルにREST API呼び出しの処理を追加
REST APIの呼び出しと呼び出した後の処理をsliceファイルに追加する。
今回呼び出すREST APIは```http://localhost:3000/mess_api```、ボディは```{["message":"testMessage"]}```を想定して、このtestMessageをstateのmessに入れて、画面に表示させます。

``` messageSlice.js

import { createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

export const messageSlice = createSlice({
  name: 'message',
  ～～～　前回と同じ　～～～
  reducers: {
  ～～～　前回と同じ　～～～
    // action内にREST APIから取ってきたデータが入っている
    getRequest: (state, action) => {
      // body内の最初のmessageキーの値をstateに入れる
      state.mess = action.payload[0].message;
    }
  },
});

// 今回追加したgetRequestもエクスポートする
export const { sayhello, sayAmount, getRequest} = messageSlice.actions;

// RESTAPIの発行とgetRequestの呼び出しをする
export const getRequestAsync = amount => async dispatch => {
  // ここでREST APIの呼び出しをする
  const response = await axios.get('http://localhost:3000/mess_api').then(response => {
    // 呼び出した結果のボディだけgetRequestに与える(与えるものを返れば上のaction引数に入る内容も変わる)
    dispatch(getRequest(response.data));
  });
};

export default messageSlice.reducer;

```

### storeファイルにthunkを追加

``` store.js

import { configureStore } from '@reduxjs/toolkit';
import thunk from 'redux-thunk';
import messageReducer from './slice/messageSlice';

export default configureStore({
  reducer: {
    message: messageReducer,
  },
  middlewares: thunk
});
```

### slice経由でstoreを使用する
コンポーネントでREST APIを発行する際には、sliceで作成したactionを呼び出してstoreを操作します。

``` App.js

import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { sayhello, sayAmount, getRequestAsync } from '../store/slice/messageSlice';

export function Message() {
  const message = useSelector(state => state.message.mess);
  const dispatch = useDispatch();
  const [messsageAmount, setMesssageAmount] = useState('2');
  ～～～　前回と同じ　～～～
        {/* sliceで作成したgetRequestAsyncアクションを使用する */}
        <button aria-label="rest get" onClick={() => dispatch(getRequestAsync())}>
          通信
        </button>
        {/* テキストボックスとボタンにインポートしたものを適用する */}
        <input aria-label="set amount" value={messsageAmount} onChange={e => setMesssageAmount(e.target.value)} />
        <button onClick={() => dispatch(sayAmount(messsageAmount))}>
          テキスト変更
        </button>
      </div>
    </div>
  );
}
```

### Reactの実行
前回同様にReactを開発用のサーバで起動してブラウザからアクセスしてください。

```

"./node_modules/.bin/webpack-dev-server"
```

通信ボタンを押すとREST APIを発行して、そのボディをstoreに格納することでWeb画面上のテキストも変わります。

# REST APIサーバを立てる
REST APIさえ発行できれば何を使用しても良いのですが、手ごろな環境がない場合に簡単なREST APIサーバを立てる方法もまとめます。
node.jsがある環境なのでJSON Serverというライブラリを使用してREST APIを立てます。

## JSON Serverのインストール

```

npm install -g json-server
```

## JSON用ファイルの作成
JSONのエンドポイントとボディを定義したファイルをJSON形式で作成します。
今回はReactからエンドポイント:```mess_api```、ボディのキー:```message```から情報を取っているためそのように記載します。

``` db.json

{
  "mess_api": [
    { "id": 1, "message": "testMessage" }
  ]
}
```

## JSON Serverの起動
先ほど作成したJSON用ファイルを指定してJSON Serverを起動します。

```

json-server --watch db.json
```

コンソールに起動した旨が表示されればREST APIサーバの完成です。

# 終わりに
ReactのWeb画面作成に関しては、ここで一旦終わりにしようかと思います。React Routerなど他のライブラリもReactにありますが、特に難しくなかったのでまとめなくて良いかなと思います。
REST APIに通信できるようになるとWeb画面で出来ることが増えるため、とても便利だと思います。しかし、Reactでのaxiosの使い方とReduxでのaxiosの使い方が結構違うので苦労しました。
次回はreact-testing-libraryの使い方でもまとめてみようと思います。