Redux createAsyncThunkFromAPI wrapper issue

huangapple go评论74阅读模式
英文:

Redux createAsyncThunkFromAPI wrapper issue

问题

https://stackblitz.com/edit/react-ts-rkekhf?file=app/redux/asyncThunkFromFetch.ts

我们使用以下助手来创建thunks:

import { createAsyncThunk } from '@reduxjs/toolkit';
import axios, { AxiosPromise, AxiosResponse } from 'axios';
import { store } from './store';

export const createAsyncThunkFromAPI = <ResponseSchema, RequestParams>(
  typePrefix: string,
  apiFunction: ApiFunction<RequestParams, ResponseSchema>
) => {
  return createAsyncThunk<ResponseSchema, RequestParams>(
    typePrefix,
    async (args, thunkApi) => {
      try {
        const response = await apiFunction(args);
        return response.data;
      } catch (e) {
        return thunkApi.rejectWithValue(e);
      }
    }
  );
};

type ApiFunction<RequestParams, ResponseSchema> = (
  axiosParams: RequestParams
) => AxiosPromise<ResponseSchema>;

export const getMobileOperatorsAPI = (): Promise<AxiosResponse<string[]>> => {
  return axios.get('https://api.com');
};

export default createAsyncThunkFromAPI;

const sliceName = 'mobile-operators';
export const fetchMobileOperators = createAsyncThunkFromAPI(
  `${sliceName}/fetchMobileOperators`,
  getMobileOperatorsAPI
);

store.dispatch(fetchMobileOperators()); //Expected 1 arguments, but got 0.ts(2554)
store.dispatch(fetchMobileOperators({})); //Ouch!!!

关于这个代码,有一点我不喜欢的是,你不能将零个参数传递给由助手创建的thunk函数。但在我们的情况下,仍然更方便使用它,而不是裸露的@redux/toolkit中的createAsyncThunk

我尝试为payload creator创建默认参数,但没有成功。但我真的不太明白我在做什么。

如何调整createAsyncThunkFromAPI以从API函数中推断args

如何以正确的方式实现相同的想法?

我需要了解哪些知识,才能自己解决这个问题?

英文:

https://stackblitz.com/edit/react-ts-rkekhf?file=app/redux/asyncThunkFromFetch.ts

We use the following helper to create thunks:

import { createAsyncThunk } from &#39;@reduxjs/toolkit&#39;;
import axios, { AxiosPromise, AxiosResponse } from &#39;axios&#39;;
import { store } from &#39;./store&#39;;

export const createAsyncThunkFromAPI = &lt;ResponseSchema, RequestParams&gt;(
  typePrefix: string,
  apiFunction: ApiFunction&lt;RequestParams, ResponseSchema&gt;
) =&gt; {
  return createAsyncThunk&lt;ResponseSchema, RequestParams&gt;(
    typePrefix,
    async (args, thunkApi) =&gt; {
      try {
        const response = await apiFunction(args);
        return response.data;
      } catch (e) {
        return thunkApi.rejectWithValue(e);
      }
    }
  );
};

type ApiFunction&lt;RequestParams, ResponseSchema&gt; = (
  axiosParams: RequestParams
) =&gt; AxiosPromise&lt;ResponseSchema&gt;;

export const getMobileOperatorsAPI = (): Promise&lt;AxiosResponse&lt;string[]&gt;&gt; =&gt; {
  return axios.get(&#39;https://api.com&#39;);
};

export default createAsyncThunkFromAPI;

const sliceName = &#39;mobile-operators&#39;;
export const fetchMobileOperators = createAsyncThunkFromAPI(
  `${sliceName}/fetchMobileOperators`,
  getMobileOperatorsAPI
);

store.dispatch(fetchMobileOperators()); //Expected 1 arguments, but got 0.ts(2554)
store.dispatch(fetchMobileOperators({})); //Ouch!!!

One thing I hate about it, you cannot pass zero arguments to a thunk function created by the helper. However in our case it's still more convenient to use it instead of bare createAsyncThunk from @redux/toolkit

I tried to make a default parameter for payload creator with no success. But I don't really understand what I'm doing here.

How to tweak createAsyncThunkFromAPI to infer args from API function?

How to implement the same idea in a proper way?

What knowledge do I miss to be able to resolve this problem by myself?

答案1

得分: 1

&lt;ResponseSchema, RequestParams = never&gt;

<ResponseSchema, RequestParams = never>

You are very close and just missing one tiny little thing. Your thunk factory will infer the type for the generics ResponseSchema and RequestParams by looking at the types of the apiFunction. This particular apiFunction has no argument so the RequestParams is getting inferred as unknown. We want to make sure that it gets inferred as never instead. Therefore we add a default value RequestParams = never. This means that no args will be accepted when the RequestParams cannot be inferred.

你很接近了,只是差一点点。您的 thunk 工厂将通过查看 apiFunction 的类型来推断泛型 ResponseSchemaRequestParams。这个特定的 apiFunction 没有参数,所以 RequestParams 被推断为 unknown。我们希望确保它被推断为 never。因此,我们添加一个默认值 RequestParams = never。这意味着当无法推断出 RequestParams 时不接受任何参数。

After making this change, the desired usage has no error and your workaround solution does have an error.

在进行此更改后,所需的用法没有错误,而您的解决方案确实出现错误。

store.dispatch(fetchMobileOperators()); // okay!
store.dispatch(fetchMobileOperators({})); // Expected 0 arguments, but got 1.(2554)


There's one last thing to check which is to make sure that it still works properly when there is a required argument. I added an additional example and sure enough it works perfectly. We get an error when the argument is missing and no error when an argument is provided.

还有最后一件要检查的事情,那就是确保当存在必需的参数时它仍然正常工作。我添加了一个额外的示例,确实它完美地工作。当参数丢失时会出现错误,当提供参数时不会出现错误。

英文:

&lt;ResponseSchema, RequestParams = never&gt;

You are very close and just missing one tiny little thing. Your thunk factory will infer the type for the generics ResponseSchema and RequestParams by looking at the types of the apiFunction. This particular apiFunction has no argument so the RequestParams is getting inferred as unknown. We want to make sure that it gets inferred as never instead. Therefore we add a default value RequestParams = never. This means that no args will be accepted when the RequestParams cannot be inferred.

export const createAsyncThunkFromAPI = &lt;ResponseSchema, RequestParams = never&gt;(

After making this change, the desired usage has no error and your workaround solution does have an error.

store.dispatch(fetchMobileOperators()); // okay!
store.dispatch(fetchMobileOperators({})); // Expected 0 arguments, but got 1.(2554)

There's one last thing to check which is to make sure that it still works properly when there is a required argument. I added an additional example and sure enough it works perfectly. We get an error when the argument is missing and no error when an argument is provided.

huangapple
  • 本文由 发表于 2023年2月18日 00:09:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75486670.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定