【问题标题】:redux-saga: function is called twiceredux-saga:函数被调用两次
【发布时间】:2019-08-15 22:27:47
【问题描述】:

我正在根据在 saga 中间件中执行的一些逻辑的结果通过从 saga 调度操作来切换模式的可见性。

我经历过:

商店

export default function configureStore(preloadedState) {
  const sagaMiddleware = createSagaMiddleware();
  const middlewares = [..otherMiddleware, sagaMiddleware, ...someMoreMiddlewares];

  const store = createStore({
    // other configuration,
    // middleWares
  })

  sagaMiddleware.run(rootRunner);
  return store;
}

减速器

const initialState = {
  activeSwitch: '1',
  modalVisibility: false,
}

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case 'TOGGLE_MODAL':
      return state.set('modalVisibility', !state.get('modalVisibility'));
    case 'UPDATE_ACTIVE_SWITCH':
      // update active switch
    default:
      return state;
  }
}

动作

export const switchOption = payload => ({
  type: 'SWITCH_OPTION',
  payload,
})

export const toggleModal = () => ({
  type: 'TOGGLE_MODAL',
})

export const updateActiveSwitch = payload => ({
  type: 'UPDATE_ACTIVE_SWITCH',
  payload,
})

组件

import switchOption from 'action';

function Component(props) {
  return <div onClick={props.switchOpt(somePayloadParameter)} />;
}

const mapDispatchToProps = state => ({
  switchOpt: (somePayloadParameter) => dispatch(switchOption(somePayloadParameter)),
})

export default connect(null, mapDispatchToProps)(Component);

RootSaga

export default function* rootRunner() {
  yield all([ fork(watcher) ])
}

传奇

function* worker(payload) {
  console.log('hey');
  yield put({'TOGGLE_MODAL'})
  // Perform some task and wait for modal ok button click
  yield take('MODAL_OK');
  if (taskSuccess) {
  yield put({ type: 'UPDATE_ACTIVE_SWITCH', someValue});
  yield put({ type: 'TOGGLE_MODAL'}};
}

export default function* watcher() {
  while(true) {
    yield actionObj = yield take('SWITCH_OPTION');
    yield call(worker, actionObj.payload);
  }
}

由于watcher 调用worker 两次,从 saga 分派了两次“TOGGLE_MODAL”,因此模态永远不可见。

如果我在watcher 中的while(true) { 之后放置一个debugger在页面加载时,该断点会被命中两次。

即使我从worker 中删除每一行,它仍然会运行两次。

为什么我的 saga 代码会运行两次?


编辑

组件

import switchOption from 'action';

function Component(props) {
  return <div onClick={props.switchOpt(somePayloadParameter)} />;
}

const mapDispatchToProps = state => ({
  // switchOption is action from action.js
  switchOpt: (somePayloadParameter) => dispatch(switchOption(somePayloadParameter)),
})

export default connect(null, mapDispatchToProps)(Component);

Redux 监控中间件在第一次调用onClick 时执行 saga 函数后,通过三个操作登录到开发工具中的控制台:

  • 'SWITCH_OPTION'
  • 'TOGGLE_MODAL' --> modalVisibility 设置为 true
  • 'TOGGLE_MODAL' --> modalVisibility 设置为 false

现在点击div 变得毫无用处,因为 MODAL 从未弹出,也没有 OK 按钮可供点击。

【问题讨论】:

  • 也许如果你添加更完整的代码,我们可以看到流程的去向。作为一个松散的尝试示例,我猜在你的 reducer 中,你总是为每种情况都有一个“return”语句,否则 UPDATE_ACTIVE_SWITCH 将被执行两次,第一次是在打开弹出窗口时,第二次是在真正更新开关时。
  • @CarlosRuana,我更新了代码,使其更完整,我似乎无法识别错误,也找不到调试 sagas 的方法。现在我正在阅读github.com/redux-saga/redux-saga/tree/master/examples 中的示例
  • 在组件中,您有“switchOption: () => dispatch(toggleVisibility())”,但我没有看到 toggleVisibility 对动作的实现以及与 toggleModal 或减速器的关系。您可以附加该代码中的某些内容吗?
  • @CarlosRuana 请查看问题的编辑部分。我已经更新了原来的问题。

标签: javascript reactjs redux generator redux-saga


【解决方案1】:

现在Component 在每次渲染时都会调用props.switchOpt。相反,创建一个可以通过引用传递的新函数,然后使用onClick 调用:

function Component(props) {
  return <div onClick={() => { props.switchOpt(somePayloadParameter); }} />;
}

【讨论】:

  • 对不起,switchOption 是我从 action.js 导入的动作,而 switchOptpropComponent。我已经编辑了这个问题。在mapDispatchToProps,我想我传递了一个参考。 switchOpt [参见 EDIT] 应该只运行 onClick。每次组件渲染时如何影响?
  • 我明白了。问题是一样的,但解决方法是不同的。我更新了我的答案。
  • 这并没有解决问题,saga 函数仍然被调用了两次,结果,TOGGLE_MODAL 动作被调度了两次。然后,SWITCH_OPTION 只是等待take('MODAL_OK'),但模式从未弹出。
  • 我认为你应该做的第一个想法是应用@RossAllen 修复,因为断点在 yield take('SWITCH_OPTION') 中停止了两次,因为你在每次渲染时都执行了该函数。您能否提供有关修复后哪个是新流程的更多信息?也许你也可以在渲染上添加一个断点。
猜你喜欢
  • 1970-01-01
  • 2018-09-06
  • 2019-12-03
  • 1970-01-01
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
相关资源
最近更新 更多