0

So, I have a reducer which needs to update the state array. The state array is expected to be:

[{productId: number; quantity: number}, ...]

Here, I match the object id, if it exists already, I need to update the quantity but if not then I need to push the the entire object to the array. To achieve this, I've tried multiple things with map, filter etc. Pushing the 1st element in the state is always fine but to update the count or to add a new element, whatever I've tried so far doesnt gives state as array of objects, instead, its array of Proxy.

The object becomes this:

Proxy{
 [[Handler]]: null
 [[Target]]: null
 [[IsRevoked]]: true
 [[Prototype]]: Object
}

Here's the latest try:

const initialState: CartProduct[] = [];

const updateCart = (state: CartProduct[], payload: CartProduct) => {
  const tempState = [...state, payload];
  console.log({ tempState });
  return tempState;

export const countReducer = createSlice({
  name: "cart",
  initialState,
  reducers: {
    increaseQuantity: (state, action) => {
      if (!state.length) {
        return updateCart(state, action.payload);
      }
      const index = state.findIndex(
        (item) => item.productId === action.payload.productId
      );
      const newState = state;
      newState[index].quantity = newState[index].quantity + 1;
      console.log(newState); //gives Proxy again

      // updateCart(newState, action.payload); //gives proxy as object in array
     
    },
  },
});

What I tried before this:

 increaseQuantity: (state, action) => {
      if (!state.length) {
        return updateCart(state, action.payload);
      }
      const newState = state.map((product) => {
        if (product.productId === action.payload.productId) {
          console.log("i increase count");
          return { ...product, quantity: product.quantity + 1 };
        }
        return product
      });
      return updateCart(newState, action.payload);
    },

1 Answers1

-1

You are hitting the state directly. This is not a good practice : const newState = state

You always must do a shallow copy of the state, then update it, and set the new state.

Here is an example to update quantity :

const newState = state.map((item) => {
  if (item.productId === action.payload.productId) {
    return {
      ...item,
      quantity: item.quantity + 1,
    };
  }
  return item;
});
Johan
  • 2,088
  • 2
  • 9
  • 37
  • It is okay to modify the draft state when using redux-toolkit's `createSlice` function. – Linda Paiste Jan 07 '23 at 19:38
  • It is not https://redux.js.org/faq/immutable-data#does-shallow-equality-checking-with-a-mutable-object-cause-problems-with-redux. – Johan Jan 07 '23 at 20:09
  • Trust me: https://redux.js.org/usage/structuring-reducers/immutable-update-patterns#simplifying-immutable-updates-with-redux-toolkit – Linda Paiste Jan 07 '23 at 20:11
  • Nice ! Didn't see that – Johan Jan 07 '23 at 20:36
  • Thanks for the information here as well Linda Paiste. @Johan the above login is broken though, it'll repeat the objects again on top updating the count. That's the 1st thing that I tried. A workable solution I found which doesn't messes with the state directly is this https://codesandbox.io/s/ykdwyn. p.s. sorry for the errors, the code works fine. – Afsheen Amroliwala Jan 08 '23 at 06:24
  • typo: above logic** – Afsheen Amroliwala Jan 08 '23 at 06:32