存储初始化后更新redux reducer

时间:2016-07-03 09:20:32

标签: redux react-redux reducers

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

1 个答案:

答案 0 :(得分:1)

是的,您可以使用Redux store的{​​{3}} api异步更新Reducer并注入一个新的。

  

这是一个高级API。如果您的应用程序实现代码,您可能需要此   拆分,并且您想要动态加载一些Reducer。您   如果你实现了一个热重载机制,也可能需要这个   终极版。

replaceReducer

为例

starter-kit中,作为reducers方法的参数传递的createStoremakeRootReducers()的结果。注意没有一个异步缩减器被传递给这个函数。

 // 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 = {}

  // ...
  }

createStore.js file中:

  • makeRootReducer函数使用默认的reducers调用combineReducers 启动所需的(如router reducer)和其他“异步”reducers作为参数传递
  • injectReducer是一个在运行时注入新reducers的函数。它在商店中调用replaceReducer api作为参数通过makeRootReducer(async)函数获取新的reducer列表

见下文:

// 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

最后,在starter-kit中,reducer被注入路由定义,如下所示:

// 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时,此技术很有用。