0

I'm receiving a state mutation error when using Immer's produce to manipulate the state.

When I create a test interface manually inside the same reducer and call produce, it seems to work as expected:

export interface ItemSliceState {
  items: Array<IItem> | null | undefined;
}

export const initialState: ItemSliceState = { items: [] };

export const updateItem: CaseReducer<
  ItemSliceState,
  PayloadAction<IItem | null | undefined>
> = (state: ItemSliceState = initialState, action) => {

  const testItem: IItem = {
    status: 1
  };

  const testItems: Array<IItems> = [testItem];

  const testState: ItemSliceState = { items: testItems };

  const nextTestState = produce(testState, draftState => {
    if (!draftState || !draftState.items) {
      return testState;
    }
    draftState.items[0].status = 2;
  });

  const nextState = produce(state, draftState => {
    if (!draftState || !draftState.items) {
      return state;
    }
    draftState.items[0].status = 2;
  });

...

// testState.items[0].status = 1
// nextTestState.items[0].status = 2
// state.items[0].status = 2
// nextState.items[0].status = 2

Why is 'state' being manipulated, while 'testState' remains unchanged when produce is called in the same way?

Sandbox with state being updated correctly: https://codesandbox.io/embed/festive-ritchie-5nf31?fontsize=14&hidenavigation=1&theme=dark

  • What happens if you change the conditional logic to not return _anything_ if the values aren't there, like `if(!draftState || !draftState.items) return;` ? – markerikson Jan 29 '20 at 16:40
  • I'm seeing the same results and still getting a state manipulation error. I think that's shorthand and it would return the same thing, I just have that to make typescript's null check happy. – William Gilmore Jan 29 '20 at 16:51
  • Weird. Any chance you can create a runnable CodeSandbox that actually demonstrates this issue – markerikson Jan 29 '20 at 16:53
  • I'll try, it'll probably take me a while to get it set up though – William Gilmore Jan 29 '20 at 17:04
  • @markerikson I made a sandbox, but the update is working correctly in the sandbox. It is a simplified version of our code, so we may be using react hooks incorrectly or have some error in our redux setup. This makes it seem like immer produce is not the problem though. – William Gilmore Jan 29 '20 at 21:04
  • 1
    Yeah, that's half the reason to put together a sandbox :) If it's reproducible, it's probably a real issue. If it's not, there's a good chance it's something unique about your setup. – markerikson Jan 29 '20 at 21:36

1 Answers1

1

The issue here was that the api was returning testItems as a class, which cannot be mutated by immer. The solution was to send interfaces instead, which immer can mutate.

  • 1
    your answer showed me a direction. thanx. adding [immerable] = true; inside my class solve the problem – dimson d Nov 29 '21 at 20:10