在 Redux Saga 任务中手动触发 RTK 查询或变异

Manually trigger RTK query or mutation inside a Redux Saga task

我在存在最好与组件分离的复杂业务逻辑的情况下使用 Redux-Saga。我们正在采用 RTK 查询,无法手动使用端点。是的,我知道 Redux 最佳实践文档建议尽可能使用 Thunk。

这个特殊的 saga 任务示例并不是使用 Redux-Saga 的好案例,但肯定存在业务逻辑如此 involved/long/complex 以至于它不属于组件的情况,而我们使用无法(优雅地)用简单的 Thunk 模拟的 saga 功能。在这个例子中,我想在后端做一个简单的突变(post 请求):

export function* addNewCustomerTask(action: ReturnType<typeof addNewCustomer>) {
  const { name, industry, defaultIdentifierObfuscationLevel } = action.payload

  if (!name) {
    yield put(setToast({ text: 'Name can not be empty', style: ToastStyle.Error }))
  }
  else if (!industry) {
    yield put(setToast({ text: 'Industry can not be empty', style: ToastStyle.Error }))
  }
  else if (!defaultIdentifierObfuscationLevel) {
    yield put(setToast({ text: 'Default identifier obfuscation level can not be empty', style: ToastStyle.Error }))
  }
  else {
    try {
      yield call(authApiEndpoints.addCustomer.initiate, action.payload)
    }
    catch  {
      console.error('Error')
    }
  }
}

yield call(authApiEndpoints.addCustomer.initiate, action.payload) 语句不执行任何操作。

如何在 Saga 中执行突变?

它是一个action creator,你需要put它的执行结果。

// start it
const promise = yield put(authApiEndpoints.addCustomer.initiate(action.payload))
// wait until finished
yield promise;

// do something with it

// unsubscribe data - will be removed from store.
promise.unsubscribe()

至于 typings:You 可能需要为 typed-redux-saga 扩展 put 的类型,例如: (我无法测试它,所以如果您必须修复某些问题,请提交对此答案的修改) 基于 https://github.com/agiledigital/typed-redux-saga/blob/591955fa5bdd73ae6f668f27a049fde21a7ffb6f/types/index.d.ts#L175-L177https://github.com/reduxjs/redux-thunk/blob/290acf90fa5afac5b49f286bb3d8fc51aa864ed3/src/index.d.ts#L25-L27

declare module 'typed-redux-saga' {

  export function put<TReturnType>(
    thunkAction: ThunkAction<TReturnType, TState, TExtraThunkArg, TBasicAction>,
  ): SagaGenerator<TReturnType, PutEffect<TReturnType>>;

}

如果你想在 Redux-Saga 中使用 RTK-Query 并且对 Typescript 没有问题你需要同时使用 putcall 然后你可以使用 select 和 RTK -查询选择器以访问数据。

const promise = yield put(
  yield call(authApiEndpoints.addCustomer.initiate, action.payload)
);
// You need to wait for the query to be done
yield promise
    
const { data } = yield select(authApiEndpoints.addCustomer.select());