在 redux sagas 中使 takeEvery 以 action.meta 为条件?

Make takeEvery conditional on action.meta in redux sagas?

我有一个 redux-saga,我只想为某些 action.meta 值触发:

function* handleUpdateSomeStuff(action): Generator {
  if (action.meta === "Special_Meta") {
    // run some code
  }
}

function* myConditionalSaga(): Generator {
  yield takeEvery(
    [ActionTypes.UPDATE_SOME_STUFF],
    handleUpdateSomeStuff
  );
}

function* itemSaga(): Generator {
  yield all([
    fork(myConditionalSaga),
    // ... more sagas
  ]);
}

目前,我在handleUpdateSomeStuff内检查action.meta是否满足某个条件。但我觉得代码永远不应该走那么远。但是,我看不到 action 参数如何在 myConditionalSaga 中可用以在那里进行检查。我在想这样的事情:

function* myConditionalSaga(action): Generator {
  if (action.meta === "Special_Meta") {
    yield takeEvery(
      [ActionTypes.UPDATE_SOME_STUFF],
      handleUpdateSomeStuff
    );
  }
}

上面的代码块是比其他任何代码都多的元代码,因为尝试将参数传递给 myConditionalSaga 会在 fork 语句中给出 TS 错误 Argument of type '(action: any) => Generator<unknown, any, unknown>' is not assignable to parameter of type '{ context: unknown; fn: (this: unknown, ...args: any[]) => any; }'.

有没有办法阻止handleUpdateSomeStuff根据动作的action.meta被调用?我确实读过 , as well as the docs on takeEvery,但我正在努力理解如何将其应用到我的场景中以获得所需的结果。

欢迎在评论中提出意见:难道我连这个都不用担心吗?让函数调用到达 myConditionalSaga 并在那里处理 if?

take 及其变体支持函数作为其第一个参数,而不是动作类型(或动作类型数组)。

所以你应该可以这样做:

function* handleUpdateSomeStuff(action): Generator {
  // this runs only for when meta is "Special_Meta"
}

function* myConditionalSaga(): Generator {
  yield takeEvery(action => {
    return (
      action.type === ActionTypes.UPDATE_SOME_STUFF &&
      action.meta === "Special_Meta"
    );
  }, handleUpdateSomeStuff);
}

这样看起来有点“罗嗦”,但如果您需要更频繁地限制基于元参数的处理程序,您当然可以创建一些实用程序助手,例如:

const typeAndMeta = (type, meta) => action => action.type === type && action.meta === meta
yield takeEvery(typeAndMeta(ActionTypes.UPDATE_SOME_STUFF, 'Special_Meta'), saga);

甚至

const takeEveryByMeta = (type, meta, saga, ...args) => {
    return takeEvery(action => action.type === type && action.meta === meta, saga, ...args);
}
yield takeEveryByMeta(ActionTypes.UPDATE_SOME_STUFF, 'Special_Meta', saga);

您可以轻松地扩展这些助手以支持 types/meta 值的数组。