如何 return redux saga watcher 的 payload

How to return the payload of redux saga watcher

示例代码


import { AnyAction } from 'redux';

interface Props {
  data: string;
}
export interface WatcherResult extends AnyAction {
  payload: PROPS
}

type TacPopulate = () => WatcherResult;
const acPopulate: TacPopulate = () => ({
  type: 'POPULATE',
  payload: {}
});


function* sagaWorker(
  action: WatcherResult
): Generator<StrictEffect, WatcherResult, Props> {
  return = {
    data: 'hello world'
  });
}

function* sagaWatcher() {
  yield takeEvery('POPULATE', sagaWorker);
}

// trigger
dispatch({
  type: 'POPULATE'
});

该方法正确分派,但 reducer 没有收到新的有效负载。 似乎我总是必须像这样做一个额外的 'yield put',这似乎是多余的代码和膨胀,我必须通过单独的 reducer 方法接收。

function* sagaWorker(
  action: WatcherResult
): Generator<StrictEffect, WatcherResult, Props> {
  yield put({
    type: 'YET_ANOTHER_ACTIONTYPE',
    payload: {
      data: 'hello world'
    }
  })
}

听起来您的要求是更改现有操作。这不是 redux-saga 的工作原理。在您的示例中,您的减速器将收到两个操作:

{type: "POPULATE"}
{type: "YET_ANOTHER_ACTIONTYPE", payload: {data: "hello world"}}

当 saga“采取”一个动作时,该动作仍会传递到商店。


如果你想停止一个动作并替换它,那么你需要自定义中间件。在这里,我们寻找具有空 payload 的“POPULATE”操作,并将其替换为具有数据的操作。

import { Middleware } from "redux";

export const replaceAction: Middleware = (store) => (next) => (action) => {
  if (action.type === "POPULATE" && !action.payload) {
    console.log("caught action");
    const data = "hello world";
    const replacedAction = {
      ...action,
      payload: { data }
    };
    return next(replacedAction);
  } else return next(action);
};

which I have to receive by separate reducer method.

也许,不总是。当您在没有数据的情况下调用 {type: "POPULATE"} 时,您的减速器是否需要做任何事情?有时“触发动作”用于在减速器中设置某种状态,如 isLoading: true 。其他时候你可以完全跳过它。


which seems superfluous code and bloat

如果您不致力于 saga,那么在 createAsyncThunk 中使用 thunk 会更容易实现。


就您的 Typescript 类型而言,acPopulate 创建的操作无效,因为 payload 是空的(可能您的实际代码中有一些东西)。您需要对此进行更改,以便在没有有效负载的填充请求和包含数据的填充成功之间存在差异。

const requestPopulate = () => ({
  type: "POPULATE_REQUEST"
});

const populateWithData = (data: string) => ({
  type: "POPULATE_SUCCESS",
  payload: {
    data
  }
});

function* sagaWorker(action: AnyAction) {
  yield put(populateWithData("hello world"));
}

function* sagaWatcher() {
  yield takeEvery("POPULATE_REQUEST", sagaWorker);
}