23
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

VALUAdvent Calendar 2019

Day 13

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

Last updated at Posted at 2019-12-14

VALU Advent Calendar 2019 13 日目の投稿になります🎉🎉
こんにちは !! VALU サービスの Web アプリケーションにおいて,クライアントサイド開発を担当している藤本です. 6 日目の投稿 でも登場しました.今回も前回同様、頑張って書いていこうと思います!

はじめに

前回の記事で取り上げた Redux について今回も引き続き書いていこうと思っています.前回は, Reducers と Store に着目したのですが,今回は主に Actions について触れていこうと思います.
また, VALU サービスにおける Redux の扱い方は前回の記事にて少し触れたので今回は割愛しています.

dispatch について

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

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

Container から dispatch して,Actions から dispatch して,Store から dispatch する.

みたいな.

...😱

たぶんこれが一番分かりやすいと思います React + Redux のフロー図解
Redux をとてもわかりやく紹介されているこの記事の「図」でも dispatch が随所で出てきています.

もっと言うと,

Container から Actionsdispatch して,場合によってはActions からも dispatch して,Store から Containerdispatch する.

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

何がわかりにくいのか

ぼくは先輩に言われていた「 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 を使った状態管理もがっつりやっていかないとなーと考えています.
最後までありがとうございました!

23
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?