首页 文章

Redux Saga热重装

提问于
浏览
14

我正在研究React&Redux项目 . 该项目过去常常使用webpack-dev-middleware和热中间件进行热重装 .

在我将Redux Saga添加到项目中之后,将一些saga中间件添加到redux商店 . 似乎每当我更改传奇代码时,热重新加载都会破坏并显示错误消息:

提供商>不支持动态更改商店 . 您很可能会看到此错误,因为您已更新到Redux 2.x和React Redux 2.x,它们不再自动热重新加载Reducer . 有关迁移说明,请参阅https://github.com/reactjs/react-redux/releases/tag/v2.0.0 .

我知道佐贺使用发电机并且它是时间依赖的 . 可以用Sagas热重新加载页面吗?就像Redux减速器在热重装过程中如何替换自身一样 .

谢谢!

2 回答

  • 24

    我正在研究一个带有redux和redux-saga的项目(但没有反应) . 我使用sagaMiddleware.run()实现了sagas的热重载,但你必须处理模块重新加载并替换reducers和sagas,如你提供的链接所示(https://github.com/reactjs/react-redux/releases/tag/v2.0.0) .

    import { createStore } from 'redux';
    import rootReducer from '../reducers/index';
    import getSagas from '../sagas';
    
    export default function configureStore(initialState) {
      const sagaMiddleware = createSagaMiddleware()
      const store = createStore(rootReducer, initialState, applyMiddleware(sagaMiddleware));
      let sagaTask = sagaMiddleware.run(function* () {
         yield getSagas()
      })
      if (module.hot) {
        // Enable Webpack hot module replacement for reducers
        module.hot.accept('../reducers', () => {
          const nextRootReducer = require('../reducers/index');
          store.replaceReducer(nextRootReducer);
        });
        module.hot.accept('../sagas', () => {
          const getNewSagas = require('../sagas');
          sagaTask.cancel()
          sagaTask.done.then(() => {
            sagaTask = sagaMiddleware.run(function* replacedSaga (action) {
              yield getNewSagas()
            })
          })
        })
      }
    
      return store;
    }
    

    需要注意的一件重要事情是 getSagas() 函数 . 它返回一个新创建的sagas生成器对象的数组,你不能在一些已经运行的sagas的数组中有一些预先创建的对象 . 如果你只在一个模块中 Build 这个数组,你可以直接使用一个常量数组,但如果你构建它来组成来自不同模块的sagas,你必须确保从所有模块重新创建sagas,所以更好的方法是所有模块导出创建功能而不是导出固定的传奇或传奇阵列 . 例如,它可能是这样的函数:

    export default () => [
      takeEvery(SOME_ACTION, someActionSaga),
      takeEvery(OTHER_ACTION, otherActionSaga),
    ]
    

    显然所有的传奇都是从头开始重新启动的,如果你有一个内部状态的复杂传奇,你会失去当前的状态 .

    一个非常类似的方法是使用动态传奇来代替调用 sagaMidleware.run() ,这是一个非常类似的解决方案,但你可以重新加载传奇的子集并以不同的方式处理它们 . 有关详细信息,请参阅https://gist.github.com/mpolci/f44635dc761955730f8479b271151cf2

  • 2

    版本 1.0.0 及更新版本中的 redux-saga 软件包更新:

    使用@mpolci解决方案,只需更改

    sagaTask.done.then(() => {

    sagaTask.toPromise().then(() => {

    一切都开始一样 .

    请参阅Task文档

相关问题