1

I've been doing some React exercises and one of them is creating shopping cart. I came across such a solution which fragment kind of perplexed me:

const addToCart = (item) => {
    const cartCopy = [...cart]
    const itemInCart = cartCopy.find(i => item.name === i.name)
    if (itemInCart) {
        itemInCart.quantity += 1
        setCart(cartCopy)
    } else {
        setCart(prevCart => [...prevCart, {...item, quantity: 1}])
    }
}

The interesting fragment is this one:

    if (itemInCart) {
        itemInCart.quantity += 1
        setCart(cartCopy)
    }

We are updating the found item's quantity. But how is it possible that this exact item updates at the same time its quantity in cartCopy? I thought that mapping over cartCopy object is necessary and using a solution presented in answer in this post: Increase the quantity of an object in an array Javascript ,React, RecoilJs

The one without mapping is more straightforward but I would like to understand what is going on under the hood.

I would be grateful for explanation. Thanks :)

bakrall
  • 465
  • 7
  • 21
  • 1
    itemInCart points to an object. Whenever we pass the value of an object somewhere (e.g. in this case passing the value of the object inside the cartCopy array to a variable called itemInCart) we are actually passing a reference to that object, meaning the itemInCart variable is just a pointer to the exact same object found inside the cartCopy array. Or to put it another way, when working with itemInCart, we are NOT working with a copy of the value found inside the cartCopy. Related SO thread: https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language – Kostas Minaidis May 19 '23 at 07:46
  • It works because for React, the only requirement is calling the function whenever the state changes, and you are doing it. Doing it in a more "functional style", considering the data as immutable and setting a new copy, it is usually done because it may have some advantages, like avoiding side effects if the object is used elsewhere, use reference equallity or being able to have a history. – Jaime Blázquez May 19 '23 at 08:11
  • 1
    On top of that, not only does this mean that itemInCart is a reference to the object inside the cartCopy, but ALSO to the original array: cart! By modifying the object (itemInCart.quantity += 1) you are actually changing the object that is found inside cartCopy AND cart. So be careful with those Object references. The [...cart] is called a Shallow Copy as it does not actually copies the nested values (item objects). If you want a Deep Copy, checkout: https://developer.mozilla.org/en-US/docs/Web/API/structuredClone – Kostas Minaidis May 19 '23 at 08:11
  • Thanks @KostasMinaidis and Jaime Blazquez for your explanations. So I will rather use solution with creating new object instead of using references – bakrall May 22 '23 at 06:29

0 Answers0