23

我正在做一个 React & Redux 项目。该项目曾经使用 webpack-dev-middleware 和 hot middleware 进行热重载。

在我将 Redux Saga 添加到项目中,并将 saga 中间件添加到 redux store 之后。似乎每当我更改 saga 代码时,热重载都会中断并显示错误消息:

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

我知道 Saga 使用生成器并且它是时间相关的。是否可以使用 Sagas 热重载页面?就像 Redux reducer 在热重载期间如何替换自己一样。

谢谢!

4

2 回答 2

41

我正在开发一个带有 redux 和 redux-saga 的项目(但没有反应)。我使用 sagaMiddleware.run() 实现了 sagas 的热重载,但您必须按照您提供的链接(https://github.com/reactjs/react-redux/releases )中的说明处理模块重载和替换减速器和 sagas /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 中拥有一些预先创建的对象。如果你只在一个模块中构建这个数组,你可以直接使用一个常量数组,但是如果你构建它是从不同的模块组成 sagas,你必须确保从所有模块重新创建 sagas,所以更好的方法是所有模块都导出创建函数而不是导出固定的 saga 或 saga 数组。例如,它可能是这样的函数:

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

显然,所有 sagas 都会从头开始重新启动,如果您有一个具有内部状态的复杂 sagas,您将丢失当前状态。

一种非常相似的方法是使用动态 saga 代替 call sagaMidleware.run(),这是一个非常相似的解决方案,但是您可以重新加载 saga 的子集并以不同的方式处理它们。有关更多信息,请参阅https://gist.github.com/mpolci/f44635dc761955730f8479b271151cf2

于 2016-11-24T10:08:37.350 回答
11

更新redux-saga版本1.0.0和更新的包:

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

sagaTask.done.then(() => {

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

一切都开始工作了。

请参阅任务文档

于 2019-03-05T11:15:24.637 回答