Search code examples
javascriptreactjsreact-reduxredux-toolkit

How to change the state of another reducer inside of the extraReducers?


Say I have the following lifecycle actions.

builder
  .addCase(loginUser.pending, (state, action) => {
    state.isLoading = true;
  }).addCase(loginUser.fulfilled, (state, action) => {
    state.isLoading = false;
    state.user = action.payload;
    // Change the Page to HomePage - using the location state from navigationSlice
    toast.success('Logged In User!');
  }).addCase(loginUser.rejected, (state, action) => {
    state.isLoading = false;
    toast.error(action.payload);
  });

I want to invoke the setLocation reducer that changes the state value from the navigation reducer. Take a look.

import { createSlice } from '@reduxjs/toolkit';
import { getCurrentPageLocation } from '../../utils';

const initialState = {
  location: getCurrentPageLocation()
};

const navigationSlice = createSlice({
  name: 'navigation',
  initialState,
  reducers: {
    setLocation: (state, action) => {
      state.location = action.payload;
    }
  },
  extraReducers: (builder) => {

  }
});

export const { setLocation } = navigationSlice.actions;

export default navigationSlice.reducer;

How can I invoke the setLocation method inside of the extraReducers (loginUser.fulfilled)? Now I know I can just dispatch this using the thunkAPI in the createAsyncThunk but I don't like doing that. I want to be able to invoke it straight from the extraReducers and preferably without importing anything.


Solution

  • Reducers are still pure functions in Redux-Toolkit, so there is not anything you can do from the loginUser.fulfilled reducer. Add an extra case in the navigationSlice state slice to handle the dispatched loginUser.fulfilled action.

    Example:

    const navigationSlice = createSlice({
      name: 'navigation',
      initialState,
      reducers: {
        setLocation: (state, action) => {
          state.location = action.payload;
        }
      },
      extraReducers: (builder) => {
        builder
          .addCase(loginUser.fulfilled, (state, action) => {
            state.location = /* update */
          });
      }
    });