【Redux】dispatchについて調べてみた

[VALU Advent Calendar 2019](https://qiita.com/advent-calendar/2019/valu) 13 日目の投稿になります🎉🎉
こんにちは !! VALU サービスの Web アプリケーションにおいて，クライアントサイド開発を担当している藤本です． [6 日目の投稿](https://qiita.com/blkclct/items/fbbd8ac8d6989f90688c) でも登場しました．今回も前回同様、頑張って書いていこうと思います！

# はじめに

前回の記事で取り上げた Redux について今回も引き続き書いていこうと思っています．前回は， Reducers と Store に着目したのですが，今回は主に Actions について触れていこうと思います．
また, VALU サービスにおける Redux の扱い方は[前回の記事](https://qiita.com/blkclct/items/fbbd8ac8d6989f90688c#redux-%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%A7%8B%E6%88%90-%E3%81%A8-%E5%88%86%E5%89%B2%E6%96%B9%E6%B3%95)にて少し触れたので今回は割愛しています．

### dispatch について

Redux の `dispatch()` ( Dispatcher )  って最初わかりにくくありませんでしたか？ぼくは、 Redux を理解しようとする上で，この `dispatch` にかなり苦しめられることになりました．

Redux には， dispatch と呼ばれる何かが多く出現します． 例えば，

**Container** から `dispatch` して，**Actions** から `dispatch` して，**Store** から `dispatch` する．

みたいな. 

**．．．😱**

[たぶんこれが一番分かりやすいと思います React + Redux のフロー図解](https://qiita.com/mpyw/items/a816c6380219b1d5a3bf)
Redux をとてもわかりやく紹介されているこの記事の「図」でも `dispatch` が随所で出てきています．

もっと言うと，

**Container** から **Actions** に `dispatch` して，場合によっては**Actions** からも `dispatch` して，**Store** から **Container** に `dispatch` する．

日本語にしようとするとこんな感じでよくわからない感じになってしまいます．

# 何がわかりにくいのか

ぼくは先輩に言われていた「 Redux は非同期が難しい」の意図がわかっていませんでした．いわゆる Redux ミドルウェア問題です． VALU サービスのフロントエンド開発における非同期処理は `redux-thunk` を使ってますが，わかりにくいのは Actions でも `dispatch` している点だと思っています．今回はその部分について重点的に話していきたいと思います．

一旦ミドルウェアに関しては， またあとで触れるとして，「わかりにくい」 `dispatch` のことを少しずつ解明していきましょう 🚀

## そもそも `dispatch` ってどういう意味？

ggると，**発送する**とか**派遣する**とか出てきます．

一旦簡潔に「**運ぶ**」にしておきましょう。

## え？何を運ぶの？

それは，**Actionオブジェクト**です．

```
action: {
  type: 'FETCH_HOGE',
  payload: { hoge: hogehoge }
}
```

こんなやつですね．

## なぜ Actions で `dispatch` するのか

Redux ミドルウェアで， `redux-thunk` を使っている場合，Actions でも， Action オブジェクトを運ぶ必要があるからです．

## VALU のフロントエンド開発ではどうしているのか？

例のごとく，以下 👇 のような API からのレスポンスがあるとします．

`🗂EventType.js`

```EventType.js
export type Event = {
  id: number, // イベントID
  title: string, // イベントタイトル
  image_url?: string, // イベントのTop画像
  address?: string, // イベントの開催地
  geotag?: string, // イベントの位置情報
  min_age: number, // 年齢制限
  start_at: string, // イベントの開始時刻
  end_at: string, // イベントの終了時刻
  detail?: string // イベントの内容詳細
};
```

このレスポンスを受けるための API 通信を Actions で行います．

```actions/event.js
import { fetchEvent } from '../api/Event';
import createAsyncActions from '../utils/createAsyncActions';

export const FETCH_EVENT = 'FETCH_EVENT';
export const fetchEventCreators = createAsyncActions(FETCH_EVENT);

export const fetchEventCreator = () => dispatch => {
  dispatch(fetchEventCreators.pending());

  fetchEvent().then(response => {
      dispatch(fetchEventCreators.fulfilled({ ...response}));
      });
    .catch(error => {
      dispatch(fetchEventCreators.rejected(error));
    });
};
```

このように `actions/event.js` の中で `dispatch` を行なっています．なぜここでも行なっているのかというと, 以下 👇 のように API 通信をおこなう際に，（当然ですが....）レスポンスの状態が Action オブジェクトとして返ってくるわけではないからです．VALU では `axios` を使っているので `Promise` オブジェクトになってるわけですね．


```api/Event.js
// @flow
import { apiClient } from './Api';

// ここの`Event`は上述した`EventType`を使用しているものとします
type EventResponse = {|
  event: Event
|};

export const fetchEvent: () => Promise<EventResponse> = () =>
  apiClient
    .get<EventResponse, void>(`Endpointが入ります`)
    .then(res => (res.type === 'Success' && res.data : null));

// 注意: apiClientの処理は割愛します．
```

では，API 通信を行なった後に再度 Action オブジェクトに変換する処理が必要になります．
上述した `actions/event.js` のコードで謎の記述があったと思うのですが（ `createAsyncActions` です），これは，VALU の自作の関数になるのですが，それを使って Action オブジェクトを以下 👇 のように作り直します．

```utils/createAsyncActions.js
import { createAction } from 'redux-actions';

export default function createAsyncActions(
  type,
  payload = null,
  meta = null
) {
  return {
    pending: createAction(`${type}_PENDING`, payload, meta),
    fulfilled: createAction(`${type}_FULFILLED`, payload, meta),
    rejected: createAction(`${type}_REJECTED`, payload, meta)
  };
}
```
こうすることで晴れて，Action が作成されたので，それを `dispatch` するわけですね．．！
つまり， Actions で Redux ミドルウェアで非同期処理するために Action を作り直す必要があるため再度 `dispatch` しているのです．

# Actionを分割すればいいのでは？ 🚀

Actions を配置するディレクトリに非同期処理が混じっていることが Redux をよりわかりにくいものにしているとぼくは考えます．
なので，非同期処理を行なっている部分とそうでない部分を単純に分けたディレクトリ構造にすればいいのではないかと考えています．
そうすれば，僕のように Actions でも `dispatch` しているけど，どういうことだろう？🤔 ということになる人が減るのではないでしょうか？
この提案は， `redux-thunk` を使っている場合に限るかもしれませんが，以下のようなディレクト構造に変えるとよりいいのでは？と思っております．

```
├── actions/
│   ├── user.js
│   └── event.js
├── middlewares/
│   ├── user.js
│   └── event.js
```

# 終わりに

Redux でも個人的には未だに難解と考えるミドルウェアについて話してみました．．かなりハイカロリーだった．．
これからも Redux とはうまく付き合いつつもそろそろ Hooks を使った状態管理もがっつりやっていかないとなーと考えています．
最後までありがとうございました！