Inject reducer arbitrarily rather than top level for redux store to replace reducer

简介: When writing a big react redux application or any SPA using redux, there is a need to split code with webpack and load reducers asynchronously. The way to load reducer asynchronously is utilizing red

When writing a big react redux application or any SPA using redux, there is a need to split code with webpack and load reducers asynchronously.

The way to load reducer asynchronously is utilizing redux store replaceReducer. There is typical sample of inject reducer like injectReducerfunction in https://github.com/davezuko/react-redux-starter-kit/blob/master/src/store/reducers.js. It only can replace the top level reducer in asyncReducers . For example.

asyncReducers = {
products: combineReducers({
list: productListReducer,
one: productReducer
}),
orders: ordersReducer
}

The injectReducer function only can replace products or orders which is top level in asyncReducers.

But there might be many chance that only asynchronously inject reducer with top one not enough since the split javascript file is still big.

Here introduce a way to inject reducer in arbitrary nested level.

The injectReducer function api change a little bit, the key is in the form of products or products.list and reducer is pure reducer not one by combineReducers . Then we can use key which is . separated to build nested object of asyncReducers which is kind of tree structure and leaf value is the pure reducer. With this information, it is easy to use combineReducers to rebuild the root reducer which is used by redux store replaceReducerfunction.

const replaceAsyncReducers = (rootReducers, keys, reducer) => {
let key = keys.shift()
if (keys.length === 0) {
rootReducers[key] = reducer
return
}
if (rootReducers[key] === undefined) rootReducers[key] = {}
let nextRootReducers = rootReducers[key]
return replaceAsyncReducers(nextRootReducers, keys, reducer)
}
const combineAsyncReducers = (asyncReducers) => {
if (typeof asyncReducers !== 'object') return asyncReducers
let combineReducerObject = {}
for (let prop in asyncReducers) {
if (!asyncReducers.hasOwnProperty(prop)) continue
let value = asyncReducers[prop]
if (typeof value === 'object') {
combineReducerObject[prop] = combineAsyncReducers(value)
} else if (typeof value === 'function') {
combineReducerObject[prop] = value
}
}
return combineReducers(combineReducerObject)
}
export const makeRootReducer = (asyncReducers) => {
let newAsyncReducers = {}
console.log(asyncReducers)
for (let key in asyncReducers) {
if (!asyncReducers.hasOwnProperty(key)) continue
newAsyncReducers[key] = combineAsyncReducers(asyncReducers[key])
}
  return combineReducers({
location: locationReducer,
...asyncReducers
})
}
export const injectReducer = (store, { key, reducer }) => {
let keys = key.split('.')
replaceAsyncReducers(store.asyncReducers, keys, reducer)
// store.asyncReducers[key] = reducer
store.replaceReducer(makeRootReducer(store.apolloClient, store.asyncReducers))
}

With this change, we can inject reducer anywhere with injectReducer(store, { key: 'products.list', reducer: productListReducer }) .

目录
相关文章
|
6月前
|
JavaScript
VUE里的find与filter使用与区别
VUE里的find与filter使用与区别
684 0
|
JavaScript 前端开发
为什么import store from ‘./store‘和 ‘./store/index‘一样
为什么import store from ‘./store‘和 ‘./store/index‘一样
151 0
|
6月前
|
JavaScript 小程序 前端开发
[Vue warn]: Error in callback for watcher “fileList“: “TypeError: Cannot create property ‘uid‘ on st
[Vue warn]: Error in callback for watcher “fileList“: “TypeError: Cannot create property ‘uid‘ on st
163 0
|
2月前
|
JavaScript
Vue+element_Table树形数据与懒加载报错Error in render: “RangeError: Maximum call stack size exceeded“
本文讨论了在使用Vue和Element UI实现树形数据和懒加载时遇到的“Maximum call stack size exceeded”错误,指出问题的原因通常是因为数据中的唯一标识符`id`不唯一,导致递归渲染造成调用栈溢出。
90 1
Vue+element_Table树形数据与懒加载报错Error in render: “RangeError: Maximum call stack size exceeded“
Vue3报错:Extraneous non-props attributes (style) were passed to component but could not be automatical
Vue3报错:Extraneous non-props attributes (style) were passed to component but could not be automatical
3748 1
|
3月前
|
存储 JavaScript 前端开发
Redux 中的 Reducer 和 Action
【8月更文挑战第31天】
62 0
|
5月前
|
前端开发 索引
解决React报错Encountered two children with the same key
解决React报错Encountered two children with the same key
|
6月前
|
存储 JavaScript 容器
Vue3通信方式之ref、$parent、provide、inject、pinia和slot
Vue3通信方式之ref、$parent、provide、inject、pinia和slot
65 0
|
6月前
|
JavaScript 前端开发
[Vue Router warn]: Component “default“ in record with path “/xx“ is a function that does not return
[Vue Router warn]: Component “default“ in record with path “/xx“ is a function that does not return
1146 0
|
6月前
|
JavaScript
[Vue warn]: Method “components“ has type “object“ in the component definition. Did you reference the
[Vue warn]: Method “components“ has type “object“ in the component definition. Did you reference the