reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.72k stars 1.17k forks source link

createAsyncThunk rejectValue type always or with undefined #2326

Closed marcusjwhelan closed 2 years ago

marcusjwhelan commented 2 years ago

I am trying to really type this createAsyncThunk so that in my createReducer in my addCase my action is the correct type. Right now with {rejectValue: string} it always has action as string | undefined

How would I prevent this | undefined from being there.

All the code paths return

import { createAction, createAsyncThunk } from "@reduxjs/toolkit";
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import { APIBaseUrl, IPokemonListItem } from "../reducers/apiReducer";

export interface IListPokemonParams {
  offset: number
  limit: number
}
export const listPokemon = createAction<IListPokemonParams>('api/listPokemon')
export const clearListPokemon = createAction('api/clearListPokemon')
export const resetListPokemon = createAction('api/resetListPokemon')

export const listPokemonAction = 
createAsyncThunk<IPokemonListItem[], IListPokemonParams, {rejectValue: string}>
(listPokemon.toString(),
  async (params: IListPokemonParams, thunkApi) => {
    try {
      return await axios.get(`https://pokeapi.co/api/v2/pokemon`, {params})
    } catch (err) {
      const errors = err as Error | AxiosError
      if (axios.isAxiosError(errors)) {
        return thunkApi.rejectWithValue(errors.message)
      } else {
        return thunkApi.rejectWithValue(errors.message)
      }
    }
  }
)

Expected return value should be a string

Snowirbix commented 2 years ago

Same issue, does anyone have an answer ?
is that because the thunk can still throw errors and not return the value from rejectWithValue ?

phryneas commented 2 years ago

There could still be a thrown error that you didn't catch - and in that case, payload would be undefined and error would be set.

phryneas commented 2 years ago

I'm on mobile right now so i can't give a concrete code example, but an explanation:

That you expect it to reject with a payload does not mean that an actual bug could not cause your thunk to throw something else instead. So now your rejected thunk could either be "rejected with payload" or "rejected with unknown error". The first will have the payload populated and the error undefined, the other will have the payload undefined and the error populated.

You can check between those two cases by checking for action.meta.rejectedWithPayload (if my memory serves me well) and then your action.payload should also be guaranteed by typescript to not be undefined.

13.05.2022 23:34:16 Marcus @.***>:

I am trying to really type this createAsyncThunk so that in my createReducer in my addCase my action is the correct type. Right now with {rejectValue: string} it always has action as string | undefined

How would I prevent this | undefined from being there.

All the code paths return

import { createAction, createAsyncThunk } from @.***/toolkit"; import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios' import { APIBaseUrl, IPokemonListItem } from "../reducers/apiReducer";

export interface IListPokemonParams { offset: number limit: number } export const listPokemon = createAction('api/listPokemon') export const clearListPokemon = createAction('api/clearListPokemon') export const resetListPokemon = createAction('api/resetListPokemon')

export const listPokemonAction = createAsyncThunk<IPokemonListItem[], IListPokemonParams, {rejectValue: string}> (listPokemon.toString(), async (params: IListPokemonParams, thunkApi) => { try { return await axios.get(${APIBaseUrl}/pokemon, {params}) } catch (err) { const errors = err as Error | AxiosError if (axios.isAxiosError(errors)) { return thunkApi.rejectWithValue(errors.message) } else { return thunkApi.rejectWithValue(errors.message) } } } )

Expected return value should be a string

— Reply to this email directly, view it on GitHub[https://github.com/reduxjs/redux-toolkit/issues/2326], or unsubscribe[https://github.com/notifications/unsubscribe-auth/ABAVQR6U2DYWAZDIDVHBHPLVJ3DEVANCNFSM5V4RMCCA]. You are receiving this because you are subscribed to this thread.[Verfolgungsbild][https://github.com/notifications/beacon/ABAVQR72DC6IEGOA2VPCRODVJ3DEVA5CNFSM5V4RMCCKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4SNHZ52Q.gif]

lucky6894 commented 3 weeks ago

Image

Image

It throws an error, why this is happening?

markerikson commented 3 weeks ago

@lucky6894 please don't post comments that are unrelated to the actual question you have.

Note that you can't pass a potentially undefined action creator to builder.addCase().