我正在使用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()
块也从未运行。关于英雄传奇取消的工作方式,我缺少什么吗?有什么简单的方法可以让我轻松处理我的传奇清理逻辑,以应对即将被取消的传奇?
答案 0 :(得分:1)
我认为您误解了任务取消在redux-saga中的工作原理。
watchSizesDraftsSaga()
相对应的任务会自行完成。task.cancel()
不执行任何操作。 yield cancelled()
块仅在您取消任务仍在运行时才执行。