skip to Main Content

Here is my slice.ts file.

interface iItem {
  Category: string;
  Id: string;
}

interface iDataState {
  Items: Array<iItem>;
}

const initialState: iDataState = {
  Items: [],
};


reducers: {
  updateItem: (state, action: PayloadAction<iItem>) => {
    console.log(state.Items);
  }
}

Every time I run dispatch(updateItem(data)); in a component, I see Proxy(Array) {0: {…}} in the console.

How can I update an item in Items if I can’t access Items to search for the item to update?

3

Answers


  1. The items look correct, it just looks like they are wrapped in a JS Proxy, which is used by many libraries these days. Describing Proxies is the beyond the scope of this answer, but in general you should be able to treat state.Items as a normal array like you expect. You can find, map, reduce, filter, and everything else you need to find and update items in the array.

    Login or Signup to reply.
  2. I suppose you are using redux toolkit

    Rtk is wrapping your reducer function with immerjs (https://redux-toolkit.js.org/usage/immer-reducers).

    This allow you to compute you next state by mutating the current state.

    Immer allow this by wrapping the state in a proxy which reimplement all the method of Array like find.

    If you want to log the wrapped state for debugging sake, you can use the function current exported by immer
    console.log(current(state));

    Login or Signup to reply.
  3. Redux-Toolkit (RTK) implements Immer.js under-the-hood, which allows you to write mutable state updates instead being forced to use the older immutable state update, e.g. shallow copying all the state that isn’t being updated. In RTK you can just directly mutate the state that you need to update.

    Example, updating the 6th element of the Items array:

    reducers: {
      updateItem: (state, action: PayloadAction<iItem>) => {
        state.Items[5] = action.payload;
      }
    }
    

    The state is a mutable draft, so if state.Items is an array, then you can use any Array methods on it.

    When you are "mutating" the state you aren’t actually mutating the state object, but rather a draft copy of it. This is the proxy object that you are seeing in the console log. If you want to console log the actual "current" state value in the reducer function RTK re-exports the current function from the immer library. Use this to wrap the draft state.

    The current function from the immer library, which takes a
    snapshot of the current state of a draft and finalizes it (but without
    freezing). Current is a great utility to print the current state
    during debugging, and the output of current can also be safely leaked
    outside the producer.

    Example:

    import { current } from '@reduxjs/toolkit';
    
    ...
    
    reducers: {
      updateItem: (state, action: PayloadAction<iItem>) => {
        ...
    
        console.log(current(state.Items));
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search