Search code examples
javascriptreactjsrecoiljs

Increase the quantity of an object in an array Javascript ,React, RecoilJs


when checking it in console the result is fine, but if replace that array in setCart its not happening , RecoilJS

const cartState=[
    { id:1, productName:'Apple',price:100,quantity:1}
    { id:2, productName:'Cherry',price:70,quantity:1}
    { id:3, productName:'Orange',price:60,quantity:1}
    { id:4, productName:'Grapes',price:69,quantity:1}
]

const [cart, setCart] = useRecoilState(cartState)

object is { id:4, productName:'Grapes',price:69,quantity:1}

const addToCart =(object) => {
        
            if(!cart.includes(object))
            {
                setCart([...cart, object])  
            }else 
            {
                let f= cart.map(items=>
                        {
                            if(items.id==object.id)
                            {
                                return {...items, quantity:items.quantity+ 1}
                            }
                            return items
                        })
                      
                        setCart(f)
                    
         }       
                    
}


Solution

  • Issue

    Array.prototype.includes basically uses shallow reference equality. Primitives and String types are always equal to themselves by value, but objects must refer to the exact same reference in memory in order for .includes to work for them. This is hardly ever the case in React though when the new item being added to the cart is typically going to be a new object as well.

    It is always safer to match objects by specific properties.

    Solution

    Search and match by the cart item ids. If some item in the cart has a matching id property, then update the cart, otherwise add the new item to the cart array.

    I suggest to also use functional state updates to correctly update from the previous state, not any cart state closed over in any scopes. These can sometimes be stale references, especially if addToCart is called in any loops to add multiple items.

    const addToCart = (newItem) => {
      if (cart.some(item => item.id === newItem.id)) {
        setCart(cart => cart.map(item => item.id === newItem.id
          ? { ...item, quantity: item.quantity + 1 }
          : item,
        ));
      } else {
        setCart(cart => [...cart, newItem]);
      }                 
    }