Redux Saga热重装

Kev*_* He 19 webpack redux webpack-hmr redux-saga react-redux

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

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

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

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

谢谢!

mpo*_*lci 30

我正在研究一个带有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;
}
Run Code Online (Sandbox Code Playgroud)

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

export default () => [
  takeEvery(SOME_ACTION, someActionSaga),
  takeEvery(OTHER_ACTION, otherActionSaga),
]
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这对我有用,但我必须使用“sagaTask.toPromise()”而不是“sagaTask.done”。另外,由于我像这样导出了 sagas: `export default function* rootSaga() { yield all(arrayOfSagas) }` 我必须 `const newSagas = require('./sagas').default` 然后只是 `sagaTask = sagaMiddleware .run(newSagas)` (2认同)

小智 6

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

使用@mpolci解决方案,然后进行更改

sagaTask.done.then(() => {

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

一切都开始一样。

请参阅任务文档