【问题标题】:Manually trigger RTK query or mutation inside a Redux Saga task在 Redux Saga 任务中手动触发 RTK 查询或突变
【发布时间】:2021-08-12 16:36:09
【问题描述】:

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

这个特殊的 saga 任务示例并不是使用 Redux-Saga 的好案例,但在某些情况下,业务逻辑非常复杂/冗长/复杂,以至于它不属于一个组件并且我们使用 saga不能(优雅地)用简单的 Thunk 模拟的功能。在这个例子中,我想在后端做一个简单的突变(发布请求):

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 中执行突变?

【问题讨论】:

    标签: redux-saga redux-toolkit rtk-query


    【解决方案1】:

    它是一个动作创建器,你需要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()
    

    至于类型:您可能需要为 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>>;
    
    }
    

    【讨论】:

    • 涂料。如果我使用 TS 忽略,这有效。不幸的是,我收到编译错误Argument of type 'ThunkAction&lt;MutationActionCreatorResult&lt;MutationDefinition&lt;NewCustomerForm, BaseQueryFn&lt;string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta&gt;, string, void, "api"&gt;&gt;, any, any, AnyAction&gt;' is not assignable to parameter of type 'Action&lt;any&gt;'. 我正在使用 typed-redux-saga 这有助于一些类型推断。
    • 我还注意到承诺类型是“任何”。使用我的旧方法(非 RTK),我能够推断出后端响应的返回类型。
    • 同样将它放在 try catch 块中也不起作用,这意味着无法捕获错误
    • 如果您yield promise.unwrap(),您应该会得到一些可捕获的东西。我添加了一个编辑,提示了修复类型的外观。
    • 我希望我对 ThunkAction 的输入方式、它们的工作方式以及如何修复这些类型不是那么一无所知。对我来说完全是黑匣子。如上所示扩展类型似乎不起作用。我使用 typed-redux-saga 的宏变体(typed-redux-saga/macro)在构建时撤消它们的代理,这一事实使事情变得更加复杂。真的希望有一种方法可以优雅地将端点发起者转换为承诺,并像我以前那样在 saga 中使用端点(对于不可行将逻辑直接放入组件的回退场景)。
    【解决方案2】:

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

    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());
    

    【讨论】:

      猜你喜欢
      • 2021-12-21
      • 2023-01-01
      • 2021-09-10
      • 2021-12-29
      • 2022-12-17
      • 2021-09-10
      • 2019-02-26
      • 2021-11-04
      • 2021-11-04
      相关资源
      最近更新 更多