UNPKG

combine-reducers-global-state

Version:

Like combineReducers that comes with redux but with global state passed through to individual reducers

150 lines (126 loc) 4.76 kB
[![Build Status](https://travis-ci.org/Velenir/combine-reducers-global-state.svg?branch=master)](https://travis-ci.org/Velenir/combine-reducers-global-state) [![npm version](https://badge.fury.io/js/combine-reducers-global-state.svg)](https://badge.fury.io/js/combine-reducers-global-state) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) [![devDependencies](https://david-dm.org/velenir/combine-reducers-global-state/dev-status.svg)](https://david-dm.org/velenir/combine-reducers-global-state?type=dev) [![Greenkeeper badge](https://badges.greenkeeper.io/Velenir/combine-reducers-global-state.svg)](https://greenkeeper.io/) [![codecov](https://codecov.io/gh/Velenir/combine-reducers-global-state/branch/master/graph/badge.svg)](https://codecov.io/gh/Velenir/combine-reducers-global-state) [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/velenir/combine-reducers-global-state/blob/master/LICENSE) # combine-reducers-global-state A substitute for the default **combineReducers** function that comes with **redux**, aiming to solve the problem of cross-state access in local slice reducers. This **combineReducers** implementation passes `globalState` as the third argument to reducers, making it available along with the local state slice. `globalState` here is the whole top-level state returned from `store.getState()` before it is sliced inside the `combineReducer`. ## Usage For example, given a store state at some point: ```js // example of a working state { // a mapped stock of items items: { uid1: { id: 'uid1', name: 'item1' // ... }, uid2: { id: 'uid2', name: 'item2' // ... }, uid3: { id: 'uid3', name: 'item3' // ... } }, // items on display display: ['uid2', 'uid3'], // currently editing editing: { uid1: { id: 'uid1', name: 'renamed_item1' // ... } } } ``` Reducers that make use of global state may look like this: ```js // reducers.js // selector that returns all item ids const getAllIds = gState => Object.keys(gState); // controls which items are currently on display export const displayReducer = (state = [], action, globalState) => { switch (action.type) { // add another item case 'ADD_ITEM': return [...state, action.payload.id]; // remove an item case 'REMOVE_ITEM': return state.filter(id => id !== action.payload.id); // add all available itemsReducer case 'ADD_ALL_ITEMS': return getAllIds(globalState); // remove all displayed items case 'REMOVE_ALL_ITEMS': return []; default: return state; } }; // selector that returns one item with given id const getItemById = (gState, id) => gState.items[id]; // edits properties of an individual item export const editingReducer = (state = {}, action, globalState) => { switch (action.type) { // grabs current state of an item // and adds it to the editing list case 'START_EDIT_ITEM': // or just overwrites its state case 'RESET_EDIT_ITEM': { const { id } = action.payload; return { ...state, [id]: getItemById(globalState, id) }; } // changes properties of an item inside the editing list case 'EDIT_ITEM': { const { id, ...props } = action.payload; return { ...state, [id]: { ...state[id], ...props } }; } // removes an item from the editing list case 'SAVE_EDIT_ITEM': case 'CANCEL_EDIT_ITEM': return { ...state, [action.payload.id]: undefined }; default: return state; } }; // selector that returns an item being edited with given id const getEditingItemById = (gState, id) => gState.editing[id]; // controls items stock export const itemsReducer = (state = {}, action, globalState) => { switch (action.type) { // copies props of a newly edited item to the item in stock case 'SAVE_EDIT_ITEM': { const { id } = action.payload; return { ...state, [id]: { ...state[id], ...getEditingItemById(globalState, id) } }; } default: return state; } }; ``` > If your selectors make time consuming calculations, it is recommended to use memoization, for example with the help of a third-party library such as [reselect](https://github.com/reactjs/reselect). Finally, `combineReducer` makes `globalState` available to all reducers passed to it: ```js import { createStore } from 'redux'; import combineReducers from 'combine-reducers-global-state'; import * as reducers from './reducers'; const reducer = combineReducers(reducers); const store = createStore(reducer); ... ```