2

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)
                    
         }       
                    
}

ASIF KAIF
  • 317
  • 1
  • 4
  • 17
  • 2
    `!cart.includes(object)` - you can't check an object like this. You'd have to target a property value like `id` with something like `findIndex`, – Andy Aug 05 '21 at 16:42

1 Answers1

2

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]);
  }                 
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • 1
    For OP's reference, see the various answers to [this question](https://stackoverflow.com/q/57828368/12162258) about the need for/uses of functional state updates – thisisrandy Aug 05 '21 at 20:48