In the Redux Tutorial, reducers for the action creators returned by createAsyncThunk
are passed as extraReducers
to createSlice
, like so:
export const fetchTodos = createAsyncThunk('todos/fetchTodos', async () => {
// async logic
})
const todosSlice = createSlice({
// omit unnecessary code
extraReducers: builder => {
builder
.addCase(fetchTodos.pending, (state, action) => {
state.status = 'loading'
})
}
})
Can the action creators be added to reducers
instead? For example:
//omit createAsyncThunk
const todosSlice = createSlice({
name: 'todos',
initialState,
reducers: {
// omit reducer cases
fetchTodos.fulfilled = (state, action) => {
// some code to update state based on action.payload
}
})
The docs say
We can't handle those inside of the createSlice.reducers field, because those generate new action types too.
Why is this the case?
No, it can't be.
The reducers
field is used to define case reducers, and generate new action types that correspond to those reducers, which will be namespaced to the slice's name
. In other words, it's used to help define new action types inside of the slice itself.
The extraReducers
is used to define case reducers that will run in response to other actions defined outside of the slice.
createAsyncThunk
defines new action types, and those will be defined outside of the slice. So, a slice must use extraReducers
to handle those actions.
If the action creators from createAsyncThunk
are added in reducers
as a computed key name, this will end up creating duplicate action types that combine the slice name
prefix and the thunk's action type strings. That means that when the thunk dispatches its actions, they won't match the types that the slice is looking for, and the reducer will never run.