Home Reference Source

src/reduce.js


/**
 * Given a state and an action, merge the action's payload into the state.
 * @param  {State} state
 * @param  {Action} action
 * @return {Reduction}
 */
export const merge = (state, action) =>
  Object.assign(state, action.payload);

/**
 * given a prop, set the action's payload prop at state.prop
 * @param  {String} prop
 * @return {Reduction}
 */
export const overwrite = prop => (state, action) =>
  Object.assign(state, { [prop]: action.payload });

/**
 * Given a prop, set the async start flag to true
 * @param  {String} prop
 * @return {Reduction}
 */
export const asyncStart = prop => state =>
  Object.assign(state, { async: Object.assign((state.async || {}), { [prop]: true }) });

/**
 * Given a prop, set the async start flag to false
 * @param  {String} prop
 * @return {Reduction}
 */
export const asyncEnd = prop => state =>
  Object.assign(state, { async: Object.assign((state.async || {}), { [prop]: false }) });

/**
 * adds an error to the `errors` list of a piece of state
 * @type {Reduction}
 */
export const addError = (state, action) =>
  Object.assign(state, { errors: (state.errors || []).concat(action.error) });

/**
 * resets the `errors` object back to the empty list.
 * @type {Reduction}
 */
export const clearErrors = state =>
  Object.assign(state, { errors: [] });

/**
 * given multiple reductions, combine them into a single reduction
 * @param  {...Reduction} reductions
 * @return {Reduction}
 */
export const compose = (...reductions) => (state, action) =>
  reductions.reduce((prevState, f) => f(prevState, action), state);

/**
 * Create a reducer with an initial state, and a reduction map (from type to
 * reduction)
 * @param  {State} init
 * @param  {ReductionMap} typeObj
 * @return {Reducer}         [description]
 */
export const byType = (init, typeObj) => (state = init, action) => {
  if (typeObj[action.type]) {
    return typeObj[action.type](state, action);
  }
  return state;
};