Search code examples
javascriptreduxreact-reduxredux-thunk

Can action creators from createAsyncThunk be added to 'reducers' instead of 'extraReducers' in createSlice?


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?


Solution

  • 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.