简体   繁体   English

redux-saga:函数被调用两次

[英]redux-saga: function is called twice

I am toggling visibility of a modal in react based on result of some logic performed in saga middleware by dispatching action from saga.我正在根据在 saga 中间件中通过从 saga 分派动作执行的某些逻辑的结果来切换反应中模态的可见性。

I went through:我经历了:

Store店铺

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

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

  sagaMiddleware.run(rootRunner);
  return store;
}

Reducer :减速机

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;
  }
}

Action :行动

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

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

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

Component :组件

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) ])
}

Saga :传奇

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);
  }
}

Modal is never visible as 'TOGGLE_MODAL' is being dispatched twice from saga, as a result of watcher calling worker twice.模态永远不可见,因为 'TOGGLE_MODAL' 从 saga 被分派两次,这是watcher两次调用worker的结果。

If I put a debugger just after while(true) { in watcher , on page load , that breakpoint is hit twice.如果我在while(true) { in watcher之后放置一个debugger在页面加载时,该断点会被命中两次。

Even if I remove every line from worker , it is still running twice.即使我从worker删除每一行,它仍然运行两次。

Why is my saga code running twice?为什么我的传奇代码运行两次?


EDIT编辑

Component :组件

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 monitor middleware logs to the console in dev tools following three actions, after executing saga function when it is called onClick for the first time: Redux 监控中间件在第一次调用onClick时执行 saga 函数后,通过三个动作记录到开发工具中的控制台:

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

Now the click on div becomes useless as MODAL never popped up and there is no OK button to click on.现在点击div变得无用,因为 MODAL 从未弹出,也没有可以点击的OK按钮。

Right now Component is calling props.switchOpt every time it renders.现在Component每次渲染时都会调用props.switchOpt Instead, create a new function that can be passed by reference and is then called with onClick :相反,创建一个可以通过引用传递的新函数,然后使用onClick调用:

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

Use takeLatest helper. 使用takeLatest助手。 It allows the saga generator to only take the latest request 它允许传奇生成器仅接受最新请求

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM