UNPKG

redux-easy-async

Version:

Redux Easy Async makes handling asynchronous actions, such as API requests, simple, reliable, and powerful

131 lines (115 loc) 4.68 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAsyncReducer = undefined; var _omit2 = require('lodash/omit'); var _omit3 = _interopRequireDefault(_omit2); var _redux = require('redux'); var _asyncConstants = require('./async-constants'); var _constants = require('./lib/constants'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var asyncDefaultState = { hasPendingRequests: false, pendingRequests: [] }; var createSingleAsyncReducer = function createSingleAsyncReducer(type) { var asyncConstants = (0, _asyncConstants.getOrCreateAsyncConstants)(type); if (!asyncConstants) { throw new Error(_constants.ERRORS.CREATE_ASYNC_REDUCER_INVALID_TYPE); } var START_TYPE = asyncConstants.START_TYPE, SUCCESS_TYPE = asyncConstants.SUCCESS_TYPE, FAIL_TYPE = asyncConstants.FAIL_TYPE; return function () { var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : asyncDefaultState; var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if ([START_TYPE, SUCCESS_TYPE, FAIL_TYPE].indexOf(action.type) > -1) { var updatedPendingRequests = void 0; if (action.type === START_TYPE) { updatedPendingRequests = [].concat(_toConsumableArray(state.pendingRequests), [ // store the meta but omit `actionCreatorArgs` as they may be large or not serializable (0, _omit3.default)(action.meta, 'actionCreatorArgs')]); } else { updatedPendingRequests = state.pendingRequests.filter(function (req) { return req.asyncID !== action.meta.asyncID; }); } return { pendingRequests: updatedPendingRequests, hasPendingRequests: updatedPendingRequests.length > 0 }; } return state; }; }; /** * Creates a requests reducer that automatically tracks the status of one or more async actions * created with {@link createAsyncAction}. As you dispatch async actions this reducer will * automatically update with number of requests, request meta for each, a boolean for whether any * requests are currently pending for this request. * @kind function * @param {Array|String|Object|Function} types - one or more async actions to track. Either a * single instance or an array of one or more of the following: a string (e.g. `"GET_POSTS"``), a * constants object created with {@link createAsyncConstants}, or an async action created with * {@link createAsyncAction}. Typically you will want to pass an array of actions to track all * async actions for your application in one place. * @return {function} Redux reducer automatically tracking the async action(s) * * @example * import { createAsyncAction, createAsyncConstants } from '`redux-easy-async'; * * // Types can async action, constants object, or string: * * // string constant * const FETCH_POSTS = 'FETCH_POSTS'; * * // async action * export const fetchUser = createAsyncAction('FETCH_USER', (id) => { * return { * makeRequest: () => fetch(`https://myapi.com/api/user/${id}`), * }; * }); * * // async constant * const fetchComments = createAsyncConstants('FETCH_COMMENTS'); * * // now we can create a reducer from the action or constants we've defined * const requestsReducer = createAsyncReducer([FETCH_POSTS, fetchUser, fetchComments]); * * // Now `requestsReducer` is reducer that automatically tracks each of the asynchronous action * // types. It's state looks something like this to start: * // { * // { * // FETCH_POSTS: { * // hasPendingRequests: false, * // pendingRequests: [], * // }, * // { * // FETCH_USER: { * // hasPendingRequests: false, * // pendingRequests: [], * // } * // { * // FETCH_COMMENTS: { * // hasPendingRequests: false, * // pendingRequests: [], * // } * // } * */ var createAsyncReducer = exports.createAsyncReducer = function createAsyncReducer(types) { if (Array.isArray(types)) { var reducers = types.reduce(function (acc, type) { var asyncConstants = (0, _asyncConstants.getOrCreateAsyncConstants)(type); if (asyncConstants) { // eslint-disable-next-line no-param-reassign acc[asyncConstants.NAME] = createSingleAsyncReducer(type); } return acc; }, {}); return (0, _redux.combineReducers)(reducers); } return createSingleAsyncReducer(types); };