我是redux架构的新手,我有这个基本的疑问,我们可以在使用combinedReducer和createStore方法创建存储后更新reducers列表吗?
可以,您可以使用Redux store
的replaceReducer
api异步更新reducer并注入新的reducer。
这是一个高级API。如果你的应用实现了代码,你可能需要这个分裂,你想要动态加载一些reducer。你可能还需要这个,如果您实现热重新加载机制回来的。
以start -kit
为例在createStore.js文件中,作为参数传递给createStore
方法的reducers
是makeRootReducers()
的结果。请注意,没有任何async reducer被传递给这个函数。
// extract of src/store/createStore.js
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'react-router-redux'
import thunk from 'redux-thunk'
import makeRootReducer from './reducers'
export default (initialState = {}, history) => {
// ...
// ======================================================
// Store Instantiation and HMR Setup
// ======================================================
const store = createStore(
makeRootReducer(), // <------------- without arguments, it returns only the synchronously reducers
initialState,
compose(
applyMiddleware(...middleware),
...enhancers
)
)
store.asyncReducers = {}
// ...
}
在reducers.js文件中:
-
makeRootReducer
函数使用默认reducer调用combineReducers
启动所需(如router
reducer)和其他"异步"reducer作为参数传递 -
injectReducer
是一个用于在运行时注入新的reducer的函数。通过makeRootReducer(async)
函数 获得一个新的reducer列表作为参数,它调用了store上的
replaceReducer
api。见下文:
// src/store/reducers.js
import { combineReducers } from 'redux'
import { routerReducer as router } from 'react-router-redux'
export const makeRootReducer = (asyncReducers) => {
return combineReducers({
// Add sync reducers here
router,
...asyncReducers
})
}
export const injectReducer = (store, { key, reducer }) => {
store.asyncReducers[key] = reducer
store.replaceReducer(makeRootReducer(store.asyncReducers))
}
export default makeRootReducer
最后,在启动器套件中,减速器被注入到路由定义中,如下所示:
// src/routes/Counter/index.js
import { injectReducer } from '../../store/reducers'
export default (store) => ({
path: 'counter',
/* Async getComponent is only invoked when route matches */
getComponent (nextState, cb) {
/* Webpack - use 'require.ensure' to create a split point
and embed an async module loader (jsonp) when bundling */
require.ensure([], (require) => {
/* Webpack - use require callback to define
dependencies for bundling */
const Counter = require('./containers/CounterContainer').default
const reducer = require('./modules/counter').default
/* ----> HERE <---- */
/* Add the reducer to the store on key 'counter' */
injectReducer(store, { key: 'counter', reducer }) // <-------
/* Return getComponent */
cb(null, Counter)
/* Webpack named bundle */
}, 'counter')
}
当你想分割一个大的应用程序,避免在启动时加载所有的reducer时,这个技术是有用的。