33

So i'm new to redux-toolkit and I want to do something really simple. I want to send some data on a POST request via this helper function. so I tried this

export const submitPaymentToServer = createAsyncThunk(
    'data/fetchAll',
    async ({ name, data }) => {
        return fetch('/payments', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                name,
                data,
            }),
        })
            .then((res) => res.json())
            .then((res) => res)
    },
)

but when I call it like so

    dispatch(
        submitPaymentToServer({
            name,
            data,
        }),
    )

typescript complains saying I don't have the right number of arguments. so how am I suppose to pass args to this function? or what is the way to do this with toolkit?

Red Baron
  • 7,181
  • 10
  • 39
  • 86

4 Answers4

40

This is what React-Redux says when you are using createAsyncThunk

You can only pass one argument to the thunk when you dispatch it. If you need to pass multiple values, pass them in a single object

So instead of

export const submitPaymentToServer = createAsyncThunk(
    'data/fetchAll',
    async ({ name, data }) => { // here you have two arguments
        return fetch('/payments', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                name,
                data,
            }),
        })
            .then((res) => res.json())
            .then((res) => res)
    },
)

You can only have one argument:

export const submitPaymentToServer = createAsyncThunk(
    'data/fetchAll',
    async (yourData) => {
        const {name, data} = yourData;
        return fetch('/payments', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                name,
                data,
            }),
        })
            .then((res) => res.json())
            .then((res) => res)
    },
)

Destructure your object inside the thunk call.

Reference: here

Shiqi
  • 837
  • 1
  • 10
  • 18
  • 12
    This is incorrect. A destructured object in the params is still just one object/param. Doesn't matter if you do it in () or in body same thing logically. createAsyncThunk does only accept one param, but it doesn't care about your destructuring. – Justin Jul 06 '22 at 16:03
  • wow, have to sift through the docs for this... thanks – Gel Oct 21 '22 at 13:43
  • This is same thing, read object destructuring ... – Bojan Mitic Feb 02 '23 at 13:01
  • Even though the code comment "here you have two arguments" is not correct because it is one argument for JavaScript, the solution still fixes the error for TypeScript. With the solution the TypeScript error "Property 'name' does not exist on type 'void'." disappears. – David Mar 31 '23 at 11:19
19

You need to actually give these arguments a type:

export const submitPaymentToServer = createAsyncThunk(
    'data/fetchAll',
     async ({ name, data }: { name: string, data: MyDataType }) => {
        return fetch('/payments', {

If you are using JavaScript with TypeScript only in the IDE, you can add a docblock for that:

const thunk2 = createAsyncThunk(
  'data/fetchAll',
  /**  @param arg {{ name: string, data: MyDataType }} */
  (arg) => {
    return fetch('/payments', {
  
phry
  • 35,762
  • 5
  • 67
  • 81
  • but this function was a js file ha. I still don't see why it complained? it wasn't complaining about the types of the arguments, it was complaining about the amount of args which was weird – Red Baron Nov 10 '20 at 07:55
  • Well, usually the amount of arguments is derived from the types, the fallback type being the TypeScript `void`, meaning "no argument". But that should not happen with pure JavaScript though. What IDE are you using? – phry Nov 10 '20 at 08:07
2

I found this in the TypeScript Redux documentation

const fetchUserById = createAsyncThunk<
  // Return type of the payload creator
  MyData,
  // First argument to the payload creator
  number
>('users/fetchById', async (userId, thunkApi) => {
  const response = await fetch(`https://reqres.in/api/users/${userId}`, {
    headers: {
      Authorization: `Bearer ${thunkApi.extra.jwt}`,
    },
  })
  return (await response.json()) as MyData
})

The argument passed into createAsyncThunk is userId which I've defined with type number.

0

If you are using typescript, consider adding createAsyncThunk() types according to docs. to see if this works for you add:

createAsyncThunk
    <any, any, any>(...)

and don't forget to use proper typing based on: https://redux-toolkit.js.org/api/createAsyncThunk

Archer
  • 11
  • 5