redux-async
RSA-compliant actions which resolve when any prop is a promise middleware for Redux.
Install
npm install --save redux-async
Adding as middleware
import asyncMiddleware from 'redux-async';
let createStoreWithMiddleware = applyMiddleware(
asyncMiddleware,
)(createStore);
Usage
// action-creators.js export const loadUsersForAdmin = adminId => { return { types: [GET_USERS_REQUEST, GET_USERS_SUCCESS, GET_USERS_FAILURE], payload: { users: api.getUsersForAdmin(adminId).then(response => response.data.users), adminId } }; } // reducers.js import { createReducer } from 'redux-create-reducer'; import { GET_USERS_REQUEST, GET_USERS_SUCCESS, GET_USERS_FAILURE } from '../constants/actions'; const initialState = {}; export default createReducer(initialState, { [GET_USERS_REQUEST](state, action) { const { adminId } = action.payload; return { isFetching: true, adminId // we always have access to all non promise properties }; }, [GET_USERS_SUCCESS](state, action) { const { adminId, users } = action.payload; return { isFetching: false, users, // all promise properties resolved adminId // we always have access to all non promise properties - same as above }; }, [GET_USERS_FAILURE](state, action) { // assert(action.error === true && action.payload instanceof Error); // when a property gets rejected then the non promise properties go in the meta object // assert(action.meta.adminId); return {errorMessage: action.payload.message}; // from Error.prototype.message }, }); // smart-container.js // ... snipped to the middle of the render function <div> { !users ? <button onClick={() => dispatch(loadUsersForAdmin(localStorage.adminId))}>Load Users</button> : (isFetching) ? (<span>isFetching for {adminId}...</span>) : (<pre>{JSON.stringify(users, null, 2)}</pre>) } { errorMessage && <div className="error">errorMessage</div> } </div>