import * as Immutable from "immutable"; import * as React from "react"; export const combineReducer = reducers => { const globalState = {}; // set default state returned by reducer and its reducer for (const [key, value] of Object.entries(reducers)) { if (typeof value === "function") { globalState[key] = value(undefined, { type: "__@@PLACEHOLDER_ACTION__" }); } else { console.error(`${value} is not a function`); } } /** * Global reducer function; this is passed to the useReducer hook * * @param {object} state * @param {object} action */ const reducerFunction = (state, action) => { let hasStateChanged = false; const updatedStateByReducers = {}; /** * this is where dispatching happens; * the action is passed to all reducers one by one. * we iterate and pass the action to each reducer and this would return new * state if applicable. */ for (const reducer in reducers) { if (reducers.hasOwnProperty(reducer)) { const currentStateByKey = state[reducer]; const currentReducer = reducers[reducer]; const returnedStateByReducer = currentReducer(currentStateByKey, action); const areStateByKeyEqual = returnedStateByReducer !== currentStateByKey; hasStateChanged = hasStateChanged || areStateByKeyEqual; updatedStateByReducers[reducer] = returnedStateByReducer; } } return hasStateChanged ? updatedStateByReducers : state; }; // return the initial state and the global reducer return [globalState, reducerFunction]; };