The problem: Async action creator with TypeScript source code of example.
The Redux Toolkit is a great library for working with Redux. It allows us to solve the complexity of configuring the Redux store and reduce the amount of boilerplate code for building applications using Redux.
The Immer is used under the hood to facilitate reducers implementation. This saves us from having to control data mutations.
To implement asynchrony, the Redux Toolkit uses Redux Thunk.
TL;DR
Typing of Redux Toolkit async action creator is the most unobvious and difficult to understand part of Redux Toolkit.
This case should allow us to control arguments and return value. Here I describe each parameter for createAsyncThunk typing.
export const incrementAsync = createAsyncThunk<
// Return type of the payload creator
number,
// First argument to the payload creator
number,
{
// Optional fields for defining thunkApi field types
rejectValue: string
}
>('counter/fetchCount', async (amount, thunkApi) => {
const response = await fetchCount(amount)
if (response.data !== 5) {
// The value we return becomes the `fulfilled` action payload
return response.data
} else {
// For example we can return validation result here
return thunkApi.rejectWithValue('Validation error! Response data was 5!')
}
})
First type number is the return type of the payload creator.
Second type number is the first argument that will be passed to the payload creator. It is our amount value.
Third type is optional fields for defining thunkApi field types.
For this definition of async action creator we can handle returned value or error.
export const counterSlice = createSlice({
extraReducers: builder => {
builder
.addCase(incrementAsync.pending, state => {
state.status = counterStatus.pending
state.error = ''
})
.addCase(incrementAsync.fulfilled, (state, action) => {
state.status = counterStatus.idle
state.value += action.payload
state.error = ''
})
// some error occurred while loading repository content
.addCase(incrementAsync.rejected, (state, action) => {
state.status = counterStatus.failed
if (action.payload) {
// For example this could be validation error handling
state.error = action?.payload
} else {
state.error = action.error.message
}
})
}
})
Payload creator for async Slice can provide some error with described type string. It was declared for rejectValue of createAsyncThunk typing. Using this sentence with Redux Toolkit automatically coerces the reducer part of the action payload type.
TL;DR
Summary:
This generic type allows us to use the type of our argument. The type of arguments passed is commented as First argument to payload creator.
In my case it’s a “number” but it can be anything. E.g. object, string, boolean etc. :
createAsyncThunk<
// Return type of the payload creator
number,
// First argument to the payload creator
number,
{
// Optional fields for defining thunkApi field types
rejectValue: string
}
>
Top comments (0)