Help us understand the problem. What is going on with this article?

Redux で複数の非同期通信を捌く方法

More than 1 year has passed since last update.

SPA を作っていると複数の API に同時に接続して、通信を待って何かをする、というケースが頻繁にあります。そういった場合、Redux ではどうするのか考えてみました。

こういった場合、ミドルウェアには redux-saga を使うのが定石かもしれませんが、あの独特の記法がどうも好きになれないのと、処理が分散してコードが追いにくくて苦手なので、今回は redux-thunk の利用で検討してみます。

サンプルのソースはこちら。
https://github.com/ANTON072/redux-multiple-ajax-sample

デモ
https://anton072.github.io/redux-multiple-ajax-sample/

View と Reducer は特に変わったことはやっていません。
https://github.com/ANTON072/redux-multiple-ajax-sample/blob/master/src/App.js

https://github.com/ANTON072/redux-multiple-ajax-sample/blob/master/src/index.js#L18

const github = (state = initialState, action) => {
  switch (action.type) {
    case ActionTypes.FETCH_EXAMPLE_REQUEST:
      return { ...state, loading: true };
    case ActionTypes.FETCH_EXAMPLE_FAILURE:
      return { ...state, loading: false };
    case ActionTypes.FETCH_EXAMPLE_SUCCESS:
      return { ...state, ...action.payload, loading: false };
    default:
      return state;
  }
};

工夫のポイントは Action Creator です。

まず Action ですが、通信まわりは REQUEST / FAILURE / SUCCESS とステータスに応じて suffix を付けておきます。今回のネタには直接関係ないですが、suffix に定型句を付けておくと、ミドルウェアでの加工も簡単にできるので何かと便利です。視認性もいい。

export const FETCH_EXAMPLE_REQUEST = 'FETCH_EXAMPLE_REQUEST';
export const FETCH_EXAMPLE_FAILURE = 'FETCH_EXAMPLE_FAILURE';
export const FETCH_EXAMPLE_SUCCESS = 'FETCH_EXAMPLE_SUCCESS';

const AJAX_A_REQUEST = 'AJAX_A_REQUEST';
const AJAX_A_FAILURE = 'AJAX_A_FAILURE';
const AJAX_A_SUCCESS = 'AJAX_A_SUCCESS';

const AJAX_B_REQUEST = 'AJAX_B_REQUEST';
const AJAX_B_FAILURE = 'AJAX_B_FAILURE';
const AJAX_B_SUCCESS = 'AJAX_B_SUCCESS';

各 API を叩く Action Creator を定義します。redux-thunk を使っているので、Promise で返すことができます。

export function ajaxA() {
  return function(dispatch) {
    dispatch({ type: AJAX_A_REQUEST });
    return fetch('https://api.github.com/')
      .then(response => response.json())
      .then(
        json => dispatch({ type: AJAX_A_SUCCESS, payload: json }),
        err => dispatch({ type: AJAX_A_FAILURE, payload: err })
      );
  };
}

export function ajaxB() {
  return function(dispatch) {
    dispatch({ type: AJAX_B_REQUEST });
    return fetch('https://api.github.com/users/anton072')
      .then(response => response.json())
      .then(
        json => dispatch({ type: AJAX_B_SUCCESS, payload: json }),
        err => dispatch({ type: AJAX_B_FAILURE, payload: err })
      );
  };
}

ajaxA と ajaxB をバンドルする Action Creator を定義します。

export function exampleAjax() {
  return function(dispatch) {
    dispatch({ type: FETCH_EXAMPLE_REQUEST });
    return Promise.all([dispatch(ajaxA()), dispatch(ajaxB())])
      .then(responces => {
        dispatch({
          type: FETCH_EXAMPLE_SUCCESS,
          payload: {
            apis: responces[0].payload,
            user: responces[1].payload
          }
        });
      })
      .catch(err => {
        dispatch({
          type: FETCH_EXAMPLE_FAILURE,
          payload: err
        });
      });
  };
}

View からはこのバンドルされた関数を実行すれば、複数の非同期通信をまとめて実行することができます。

async / await を使うともうちょいオシャレな書き方もできるんですかね。

ANTON072
ReactとRailsが好きです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした