当使用EjectSaga取消传奇任务时,yield cancelled()不会触发

时间:2018-11-16 01:15:04

标签: reactjs redux react-redux redux-saga

我正在使用react-boilerplate injectSaga / ejectSaga功能(reference),却遇到了取消我的传奇的问题。

tl; dr-卸载具有注入的传奇的组件时,通过task.cancel()取消传奇的取消,但这并没有触发实际的传奇本身(即yield cancelled()没有触发)

我将自己的传奇注入我的容器中(使用react-router v4和redux):

const enhance = compose(
  withRouter, // from react-router 4
  injectSaga({ key: 'stuffDirectory', saga: stuffDirectorySaga }),
  connect(mapStateToProps, mapDispatchToProps),
  // other things that we're composing
);

injectSaga函数执行以下操作:

export default ({ key, saga, mode }) => WrappedComponent => {
  class InjectSaga extends React.Component {
    static WrappedComponent = WrappedComponent;
    static contextTypes = {
      store: PropTypes.object.isRequired,
    };
    static displayName = `withSaga(${WrappedComponent.displayName ||
      WrappedComponent.name ||
      'Component'})`;

    componentWillMount() {
      const { injectSaga } = this.injectors;

      injectSaga(key, { saga, mode }, this.props);
    }

    componentWillUnmount() {
      const { ejectSaga } = this.injectors;

      ejectSaga(key);
    }

    injectors = getInjectors(this.context.store);

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return hoistNonReactStatics(InjectSaga, WrappedComponent);
};

这是我的传奇(非常简单):

export function* watchSizesDraftsSaga() {
  try {
    let stuffWeLookingFor = yield select(selectStuff());

    // waiting for stuff here

    yield put( moveStuffOver(stuffWeLookingFor) );
    // everything works fine here, page works as expected and stuff has been found
  } finally {
    if (yield cancelled()) {
      // PROBLEM: when the saga is ejected via ejectSaga, this condition never happens
      yield put( cleanStuffUp() );
    }
  }
}

saga注入正常工作-每次安装组件时,我都能清楚地看到在redux中调用并捕获了动作。在sagaInjectors.js中的特定react-boilerplate文件中,我找到了取消注入的sagas的特定行:

if (Reflect.has(store.injectedSagas, key)) {
  const descriptor = store.injectedSagas[key];
  if (descriptor.mode && descriptor.mode !== DAEMON) {
    // the task is cancelled here
    descriptor.task.cancel();
    // we verify that the task is cancelled here - descriptor.task.isCancelled() returns true if we log it

    // Clean up in production; in development we need `descriptor.saga` for hot reloading
    if (process.env.NODE_ENV === 'production') {
      // Need some value to be able to detect `ONCE_TILL_UNMOUNT` sagas in `injectSaga`
      store.injectedSagas[key] = 'done'; // eslint-disable-line no-param-reassign
    }
  }
}

即使任务已成功取消,我的yield cancelled()块也从未运行。关于英雄传奇取消的工作方式,我缺少什么吗?有什么简单的方法可以让我轻松处理我的传奇清理逻辑,以应对即将被取消的传奇?

1 个答案:

答案 0 :(得分:1)

我认为您误解了任务取消在redux-saga中的工作原理。

  1. 您与watchSizesDraftsSaga()相对应的任务会自行完成。
  2. 然后task.cancel()不执行任何操作。

yield cancelled()块仅在您取消任务仍在运行时才执行。