You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
Declaratively code-split your redux store and make containers own entire redux flow using redux-store-manager
Installation
yarn add redux-store-manager
Problem
rootReducer is traditionally created manually using combineReducers and this makes code-splitting reducers based on how widgets consuming their data are loaded(whether they are in the main bundle or on-demand bundles) hard.
Bundler cant tree-shake or dead code eliminate the rootReducer to not include reducers whose data is not consumed by any container components
Solution
Let the containers that are going to consume the data stored by a reducer and trigger actions take responsibility of adding a reducer to the store.This makes the container owning the entire redux flow by linking
Actions as component props viamapDispatchToProps
Reducer responsible for updating the data viastoreManager.registerReduers
Data as component props viamapStateToProps
Use the redux store's replaceReducer API whatever reducers are registered when an on-demand chunk loads the store gets refreshed with the new rootReducer.
Documentation
storeManager is a singleton that has the following methods
1. storeManager.registerReducers(reducerMap)
reducerMap is an object with reducer namespaces as keys and reducer definitions as values (similar to the object you pass to combineReducers).
This method is used in container components to register the reducer on the store to be created.
createStore method takes the same arguments that createStore function of redux library without the rootReducer argument.
createStore is called to pass the store prop to component.
both the initialState, storeEnhancer are optional.
3. storeManager.refreshStore()
refreshStore is called when the on-demand build chunk is loaded, to replace the rootReducer of the store.
The refreshed store will include the registered reducers in the on-demand chunk that was just loaded.
Example of usage in a React app
Root.js
import{Provider}from'react-redux';importstoreManagerfrom'redux-store-manager';importAppfrom'./containers/AppContainer';exportdefaultfunctionRoot(){return(// creates store with all the reducers registered by container components<Providerstore={storeManager.createStore(initialState,storeEnhancer)}><App></Provider> )}/* ReactDOM.render(<Root/>, document.getElementById('root')); */
App.js
importReact,{Component}from'react';import{withRefreshedStore}from'redux-store-manager';importSimpleWidgetContainerfrom'./containers/SimpleWidgetContainer';exportdefaultclassAppextendsReact{state={OnDemandWidgetContainer:null};componentWillMount(){// when loading a widget on-demand along with the component codebase the reducers are alsowithRefreshedStore(import('./containers/SimpleWidgetContainer')).then((module)=>{this.setState({OnDemandWidgetContainer:module.default});});}render(){const{OnDemandWidgetContainer}=this.state;return(<><SimpleWidgetContainer/>{OnDemandWidgetContainer ?<OnDemandWidgetContainer/> :null}</>);}}
SimpleWidgetContainer.js
importstoreManagerfrom'react-store-manager';import{connect}from'react-redux';importSimpleDemandWidgetfrom'../components/SimpleWidget';importsimpleDemandWidgetReducerfrom'../reducers/simopleWidgetReducer';import{getSimpleWidgetData}from'../actions';// reducer and its initialStatw will be added to the store.storeManager.registerReducers({simpleWidgetData:simpleWidgetDataReducer});constmapStateToProps=(state)=>({simpleWidgetData:state.simpleWidgetData});constmapDispatchToProps={ getSimpleWidgetData};exportdefaultconnect(mapStateToProps,mapDispatchToProps)(OnDemandWidget);
OnDemandWidgetContainer.js
importstoreManagerfrom'react-store-manager';import{connect}from'react-redux';importOnDemandWidgetfrom'../components/OnDemandWidget';importonDemandWidgetReducerfrom'../reducers/onDemandWidgetReducer';import{getOnDemandWidgetData}from'../actions';/* * reducers registered in on-demand chunks will be added to redux store * only when the on-demand chunk is loaded */storeManager.registerReducers({onDemandWidgetData:onDemandWidgetDataReducer});constmapStateToProps=(state)=>({onDemandWidgetData:state.onDemandWidgetData});constmapDispatchToProps={ getOnDemandWidgetData};exportdefaultconnect(mapStateToProps,mapDispatchToProps)(OnDemandWidget);
About
Declaratively code-split your redux store and make containers own entire redux flow using redux-store-manager