在存储初始化后更新redux reducer



我是redux架构的新手,我有这个基本的疑问,我们可以在使用combinedReducer和createStore方法创建存储后更新reducers列表吗?

可以,您可以使用Redux storereplaceReducer api异步更新reducer并注入新的reducer。

这是一个高级API。如果你的应用实现了代码,你可能需要这个分裂,你想要动态加载一些reducer。你可能还需要这个,如果您实现热重新加载机制回来的。

以start -kit

为例

在createStore.js文件中,作为参数传递给createStore方法的reducersmakeRootReducers()的结果。请注意,没有任何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时,这个技术是有用的。

最新更新