when i increment the counter it increases by 2 not one. i am using react context for this

Viewed 785

here i called a function addItem in which i increases the value of th cart

 <CartItem
                key={`cartItem-${item.item_id}`}
                onIncrement={() => addItem(item)}
                onDecrement={() => removeItem(item)}
                onRemove={() => removeItemFromCart(item)}
                data={item}
              />

and my context is

const addItemHandler = (item, quantity = 1) => {
    dispatch({ type: 'ADD_ITEM', payload: { ...item, quantity } });
  };

and my reducer for add item in reducer.js

export const addItemToCart = (state, action) => {
  const existingCartItemIndex = state.items.findIndex(
    (item) => item.item_id === action.payload.item_id
  );
  if (existingCartItemIndex > -1) {
    const newState = [...state.items];
    newState[existingCartItemIndex].quantity += action.payload.quantity;
    return newState;
  }
  return [...state.items, action.payload];
};
const reducer = (state, action) => {
  switch (action.type) {
    case 'ADD_ITEM':
      return { ...state, items: addItemToCart(state, action) };
    default:
      throw new Error(`Unknown action: ${action.type}`);
  }
};

this code increases the counter by 2 instead on 1.

1 Answers

The reason that your quantity is being incremented twice is because you would be using React.StrictMode which invokes your reducer twice.

This is intentional behaviour and it helps detect side-effects. You must note that if your reducer is a pure function, such a effect will not happen.

In your case you have mutated the quantity value in state which is why you a double increment. Even though you use spread syntax to copy the array, it only performs a shallow copy and the inner objects within it still hold the same reference.

To update it properly you must update the reducer in an immutable way. You can use Array.prototype.slice for this purpose

export const addItemToCart = (state, action) => {
  const existingCartItemIndex = state.items.findIndex(
    (item) => item.item_id === action.payload.item_id
  );
  if (existingCartItemIndex > -1) {
        const newState = [
           ...state.items.slice(0, existingCartItemIndex),
           {...state.items[existingCartItemIndex], quantity: state.items[existingCartItemIndex].quantity + 1},
           ...state.items.slice(existingCartItemIndex + 1)
        ];
        return newState;
    }
  return [...state.items, action.payload];
};
Related