Search code examples
reactjse-commerce

ReactJS handling quantiteis in cart


in an ecommerce project, i made a cart which its functionality can be seen here codesandbox.io/s/confident-torvalds-smg72?file=/src/App.js

my main problem is that, no matter the number i put in the field, the product is incremented only by 1

here's my guess at explaining it

  • current value: 1 / I type 4
  • onChange is triggered with quantity 4 and previous value 1
  • adjustCart run, and loop 3 times
  • first time in loop addToCart is run it update the cart and so the value in the quantity field (it is updated to 2) and also the name is updated (with a value like {ID}_2) since the filed changed onChange is triggered again
  • this time onChange will have current value=2 and previous_value=2
  • so product_to_add=0 and nothing happen

cant find a good solution with a good usability (i can put an update cart button, but i cant handle the onChange with, since i dont know how many filed i have, i can use a +- solution, but it would be better to put an arbitrary number in fileld and automatically update cart) if you have suggestions, of any kind...


Solution

  • I think the reason you're seeing issues is because if you call setCart, the value of cart doesn't actually update until the next render. So when you call setCart([...cart]) a second time you are expanding the original version of cart

    You can get around this by using a function updater, where you pass a function which receives the latest version of cart as it's first parameter:

    setCart((latestCart) => ([...latestCart, ...newCart]);
    

    I think you should consider restructuring your cart state to better reflect how you are using the data, for example if you used:

    const [cart, setCart] = useState([
        { id: 1, name: "product 1", qty: 1 },
        { id: 2, name: "product 2", qti: 1 },
    ]);
    
    // you can update the quantity using one call to setCart:
    setCart(cart.map(item => {
        if (item.id === itemIWantToUpdate) {
             return { ...item, qty: newQuantity };
        }
        return item;
    }));