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 }) .

目录
相关文章
|
10月前
|
JavaScript 前端开发
为什么import store from ‘./store‘和 ‘./store/index‘一样
为什么import store from ‘./store‘和 ‘./store/index‘一样
133 0
|
10月前
|
前端开发 JavaScript BI
轻松搞定vue3+Pinia-2-修改state-patch-actions
轻松搞定vue3+Pinia-2-修改state-patch-actions
216 0
|
11月前
|
JavaScript
Spartacus 中的 navigation item reducer 实现
Spartacus 中的 navigation item reducer 实现
|
12月前
|
存储 JavaScript 前端开发
Angular Ngrx Store 里 State 和 Reducer 的绑定关系是如何实现的
Angular Ngrx Store 里 State 和 Reducer 的绑定关系是如何实现的
|
18天前
|
存储 JavaScript 前端开发
Redux 中的 Reducer 和 Action
【8月更文挑战第31天】
21 0
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
2948 1
|
4月前
|
存储 JavaScript 容器
Vue3通信方式之ref、$parent、provide、inject、pinia和slot
Vue3通信方式之ref、$parent、provide、inject、pinia和slot
38 0
|
4月前
|
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
690 0
|
JavaScript
[Vue warn] Error in callback for immediate watcher “data“ “TypeError Cannot read property ‘reduce
[Vue warn] Error in callback for immediate watcher “data“ “TypeError Cannot read property ‘reduce
328 0
Dva中在effects中获取state的值
Dva中在effects中获取state的值
313 0