商店初始化后更新 redux reducer

update redux reducers after store initialization

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

是的,您可以使用 Redux store.

replaceReducer api 更新减速器并异步注入新的减速器

It is an advanced API. You might need this if your app implements code splitting, and you want to load some of the reducers dynamically. You might also need this if you implement a hot reloading mechanism for Redux.

以这个为例starter-kit

createStore.js file 中,作为参数传递给 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 file中:

  • makeRootReducer 函数使用默认减速器调用 combineReducers 启动所需(如 router 减速器)和其他 "asynchronously" 减速器作为参数传递
  • injectReducer 是一个函数,用于在运行时注入新的 reducer。它在商店上调用 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

最后,在初学者工具包中,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')
  }

当您想要拆分大型应用程序并避免在启动时加载所有减速器时,此技术很有用。