Search code examples
javascriptngrx-store

How do I use the spread operator to replace a value in an array


I have the following object:

const initialState = {
cart: {
    products: []
},
numberOfItems: 0

}

In the following function, I want to replace the quantity of one of the products in the products array.

"newItems" is the object containing the changed quantity.

on(increaseItemQuantity, (state, action) => {
    const newItems = increaseQuantity(state, action.itemId, action.size);

    const newState  = {
        ...state,
        ...state.cart,
        products: [...newItems]
    }

    return newState;
}),

I expect the products array within the cart to contain an object with the new quantity, instead a new products array is created within the state.

The starting cart looks like this:

{
    cart:
        products: [
            {quantity: 9, size: 'XX-Large', _id: '61814f61efae17ff8c7d7a2c'},
            {quantity: 1, size: 'Medium', _id: '618152d8fe84f566364585f0'}
        ]
}

I want the item showing quantity 9 to be replaced with the one showing quantity 10 below:

{
cart:
    products: [
        {quantity: 10, size: 'XX-Large', _id: '61814f61efae17ff8c7d7a2c'},
        {quantity: 1, size: 'Medium', _id: '618152d8fe84f566364585f0'}
    ]
}

Instead an additional product array is added to the newState as shown below and the original in cart is never replaced:

newState 
  cart:
      products: (7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
     _id: "617046de3eaaaa7221c1924e"
  products: (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, Array(7)]




const increaseQuantity = (state, itemId, size) => {
    console.log('state.cart.products', state.cart.products)
    const item = state.cart.products.find(item => item._id === itemId && 
        item.size === size);

    const newItem = {...item};

    ++newItem.quantity;

    let  newItems = state.cart.products.filter(item => item._id !== 
          itemId   && item.size !== size);

    newItems.push(newItem);

    return newItems;
}

Solution

  • Instead of finding and filtering it might be easier to just map over the array, and if the product id matches a search id update the quantity value of that product object, and return it, otherwise just return an unchanged object.

    You can then update your state. This creates a new state object, preserves the old state, adds a new property for the cart, preserves the properties of the existing cart, and then adds the new updatedArray to products.

    return {
      ...state,
      cart: {
        ...state.cart,
        products: updated
      }
    };
    

    const state={cart:{products:[{quantity:9,size:"XX-Large",_id:"61814f61efae17ff8c7d7a2c"},{quantity:1,size:"Medium",_id:"618152d8fe84f566364585f0"}],anotherProp1:1,anotherProp2:2}};
    
    function updateItem(state, id) {
    
      const { products } = state.cart;
    
      const updated = products.map(product => {
        if (product._id === id) {
          return { ...product, quantity: product.quantity + 1 };
        }
        return product;
      });
    
      return {
        ...state,
        cart: {
          ...state.cart,
          products: updated
        }
      };
    
    }
    
    const id = '61814f61efae17ff8c7d7a2c';
    
    const updatedState = updateItem(state, id);
    
    console.log(updatedState);