Search code examples
javascriptreactjsreduxredux-toolkit

Why reducer in createSlice can't change state in different ways?


I'm curious to know what's the difference between these 2 ways of changing state (commented and non-commented)? The first one leads to problem when dispatches doesn't work well. Why is that?

export const correctiveSlice = createSlice({
  name: "corrective",
  initialState: initialCorrectiveState,
  reducers: {
    correctContent: (state, action: PayloadAction<CorrectiveState>) => {
      // This code doesn't work
      // state = {
      //   item: {
      //     id: action.payload.item.id,
      //     text: action.payload.item.text,
      //   },
      //   edit: action.payload.edit,
      // };

      // This code works
      state.item = action.payload.item;
      state.edit = action.payload.edit;
    },
  },
}); 

I'm doing classic todo-list app, but instead using Context API I'm using redux-toolkit/react-redux libraries. When I tried to use first way to change state, it didn't change.


Solution

  • If you assign state to a completely new object with state = {...}, you're not modifying the passed state. Instead, You're re-assigning new local variable to a new value, i.e. changing the reference. The underlying methods only have access to the state they've passed to the reducer method, which remains unchanged. Actually, this is not a matter of Redux or React, but a basic behavior of JavaScript - or any language which doesn't work with explicit pointers.

    To modify the underlying variable, you either have to modify it's properties as you did with state.item = action.payload.item etc., or by merging it as described here, for example. Modifying the state is only allowed if you're using redux-toolkit, though!

    Alternatively, you return the new state with something like return action.payload instead of modifying the passed state. In that case, the returned item will replace the previous state. This is a Redux feature.