Handling actions dispatched by Redux promise middleware is simple by default.
const FOO_TYPE = 'FOO';​// Dispatch the actionconst fooActionCreator = () => ({type: FOO_TYPEpayload: Promise.resolve('foo')});​// Handle the actionconst fooReducer = (state = {}, action) => {switch(action.type) {case `${FOO_TYPE}_PENDING`:return;​case `${FOO_TYPE}_FULFILLED`:return {isFulfilled: true,data: action.payload};​case `${FOO_TYPE}_REJECTED`:return {isRejected: true,error: action.payload};​default: return state;}}
Optionally, the default promise suffixes can be imported from this module.
import { ActionType } from 'redux-promise-middleware';
This can be useful in your reducers to ensure types are more robust.
const FOO_PENDING = `FOO_${ActionType.Pending}`;const FOO_FULFILLED = `FOO_${ActionType.Fulfilled}`;const FOO_REJECTED = `FOO_${ActionType.Rejected}`;
In a large application with many async actions, having many reducers with this same structure can grow redundant.
To keep your reducers DRY, you might see value in using a solution like type-to-reducer.
import typeToReducer from 'type-to-reducer';​const BAR_TYPE = 'BAR';​// Dispatch the actionconst barActionCreator = () => ({type: BAR_TYPEpayload: Promise.resolve('bar')});​// Handle the actionconst barReducer = typeToReducer({PENDING: () => ({// ...}),REJECTED: (state, action) => ({isRejected: true,error: action.payload}),FULFILLED: (state, action) => ({isFulfilled: true,data: action.payload})}}, {});