Skip to content
Advertisement

Unable to increment or decrement my quantity value React JS

So I am building a shopping cart, I am done with most of my code but when I try to increment or decrement the value of a product quantity from cart it just fetches me the value of current quantity it doesn’t get updated. I am unable to understand where I am making the mistake.

This is my cart.js file

import React from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';


export default function Cart({ cart, setCart }) {
  const getTotalSum = () => {
    return cart.reduce(
      (sum, { cost, quantity }) => sum + cost * quantity,
      0
    );
  };
  const RemoveFromCart = productToRemove => {
    setCart(cart.filter(product => product !== productToRemove));
  };
  const clearCart = () => {
    setCart([])
  }

  const setQuantity = (product, amount) => {
    const newCart = [...cart];
    newCart.find(item => item.name === product.name)
      .quantity = amount;
    setCart(newCart)
  };

  let valueCal =(v)=>{
    console.log(v)
    return v++
  }
  let decrement =(v)=>{
    console.log(v)
    return v--
  }


  return (
    <>
      <h1>Cart</h1>
      {cart.length > 0 && (<button onClick={clearCart}>Clear Cart</button>)}
      <div className="products">
        {cart.map((product, idx) => (
          <div className="product" key={idx}>
            <h3>{product.name}</h3>
            <h4>RS: {product.cost}</h4>
            
            <img src={product.image} alt={product.name} />
            Quantity: {product.quantity}
            <button
              value={product.quantity}
              onClick={(e) =>
                setQuantity(
                  product,
                  parseInt(valueCal(e.target.value))
                )
              }
            >Add</button>
            <button
              value={product.quantity}
              onClick={(e) =>
                setQuantity(
                  product,
                  parseInt(decrement(e.target.value))
                )
              }
            >
              Drop
            </button>
            <button onClick={() => RemoveFromCart(product)}>
              Remove
        </button>
          </div>
        ))}
      </div>
      <div>
        Total cost: Rs: {getTotalSum()}
      </div>
    </>
  )
}

Advertisement

Answer

Issue

The issue appears to be state mutation. When you find a matching product and set the quantity property you are mutating the product object and since object is still shallow reference equal React bails on rerendering it. This is why you see stale UI.

const setQuantity = (product, amount) => {
  const newCart = [...cart];
  newCart.find(item => item.name === product.name).quantity = amount; // mutation
  setCart(newCart)
};

Additionally, the Array.prototype.find method can potentially return undefined if a matching product item isn’t found, and if this happens your code will throw an error when it attempts to access quantity of undefined.

You’ve also some odd logic around incrementing/decrementing the quantity by 1. Just add/subtract 1 from the quantity.

Solution

Shallow copy all state that is being updated.

const setQuantity = (product, amount) => {
  setCart(cart => cart.map(item => item.name === product.name ? {
    ...item,
    quantity: item.quantity + amount
  } : item));
};

Fix the button callbacks. Just let the amount be what is added to the quantity.

<button onClick={(e) => setQuantity(product, 1)} >
  Add
</button>
<button onClick={(e) => setQuantity(product, -1)} >
  Drop
</button
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement