UNPKG

redux-tiles

Version:

Library to create and easily compose redux pieces together in less verbose manner

84 lines (75 loc) 2.53 kB
import { Action, Reducer } from "redux"; import { get, isFunction, mapValues } from "../utils"; import { ReducerObject } from "./types"; /** * @overview create reducer function from the object * @param {Any} initialState – initial state of this part of the store * @param {Object} handlers – object with keys as action types, and * reduce functions to change store as values * @return {Function} – function to act as a reducer */ export function createReducerFromObject( initialState: any, handlers: ReducerObject ): Reducer<any> { return function reducer(state: {} = initialState, action: Action): {} { const handler: Function | {} = handlers[action.type]; return typeof handler === "function" ? handler(state, action) : state; }; } /** * @overview create reducer from the object, with creating reducing functions * @param {Any} initialState – initial state of this part of the store * @param {Object} handlers – object with keys as action types, and * newValues to set at store as values * @return {Function} – function to act as a reducer */ export function createReducer( initialState: any, handlers: ReducerObject ): Reducer<any> { return createReducerFromObject( initialState, mapValues(handlers, (value: any) => (state: any, action: Action): any => reducerCreator({ state, action, newValue: isFunction(value) ? value(state, action) : value }) ) ); } /** * @overview reducer function, which changes the state with new values * @param {Object} action – reducer action object, with type and payload * @param {Object} state – previous redux state in this branch * @param {Any} newValue – new value to set up in state in corresponding path * @return {Object} – changed reducer */ export function reducerCreator({ action, state, newValue }: any): any { const { path } = action.payload; const hasNoNestInStore: boolean = !path; if (hasNoNestInStore) { return newValue; } let result: any = {}; let lookupPath: string[]; const length: number = path.length; for (let i: number = length - 1; i >= 0; i = i - 1) { const el: string = path[i]; const isLastItem: boolean = i === path.length - 1; const newNestedResult: any = { [el]: isLastItem ? newValue : result }; lookupPath = path.slice(0, i); const oldState: any = get(state, lookupPath) || {}; result = { ...oldState, ...newNestedResult }; } return { ...state, ...result }; }