Skip to content

Pass values from child component to parent component – pick quantity values in child component rendering them on the parent component as a sum

I don’t have much experience in React so I want to use the quantity selected from each product and sum it up so that it can be shown in a shopping cart. I need help passing the quantities of each product to the main/root component which is App.js to make the sum to be shown on the cart possible. I prefer using functional components.
Here is my code in the two files
• App.js

import {useState}  from "react";
import './App.css';
import ProductComponent from "./components/ProductComponent.jsx";
import RedmiPhoto from "./images/redmi_note_10_5G_phone.jpeg";
import HuaweiPhoto from "./images/huawei_p40_pro_phone.jpg";
import OppoPhoto from "./images/Oppo_Reno_5F.jpg";

function App() {

  const [productsData, setProductsData] = useState([
    {name: "Oppo", cost: 13, photo: <img src={OppoPhoto} width="100px" height="100px" alt="Oppo Photo" /> },
    {name: "Redmi", cost: 15, photo: <img src={RedmiPhoto} width="100px" height="100px" alt="RedMi Photo" />},
    {name: "Huawei", cost: 17, photo: <img src={HuaweiPhoto} width="100px" height="100px" alt="Huawei Photo" />}
  ]); 

  return (
    <div className="body-section">
      {productsData.map((productData, i) => <ProductComponent key={i} name={productData.name} cost={productData.cost} photo={productData.photo} />)}
      {/* <p><img src={iPhone} /></p> */}
    </div>
  );
}

export default App;

• ProductComponent.jsx

import {useState} from "react";

const ProductComponent = ({name, cost, photo }) => {

  const [prodQuantity, setProdQuantity] = useState(0);

  const increment = () => {
    setProdQuantity(prodQuantity + 1);
  };

  const decrement = () => {
    if(prodQuantity > 0)
      setProdQuantity(prodQuantity - 1);
  };

  return(
    <div className="product">
      <div>
        <div> &nbsp;&nbsp; {photo}</div>
        <p> &nbsp; {name}</p>
        <p> &nbsp; Cost: ${cost}</p>
        &nbsp; Quantity:  <button onClick={decrement}>-</button>&nbsp;<button>{prodQuantity}</button>&nbsp;<button onClick={increment}>+</button>&nbsp;<button>Add to Cart</button>
      </div>
    </div>
  );
};

export default ProductComponent;

The code is available in this repository.

Picture of current app state.
enter image description here

Answer

You can pass a callback function handler from parent to child components, and then update the quantity of the product in this callback function, try this:

function App() {
  const [productsData, setProductsData] = useState([
    {name: "Oppo", cost: 13, photo: <img src={OppoPhoto} width="100px" height="100px" alt="Oppo Photo" />, quantity: 0 },
    {name: "Redmi", cost: 15, photo: <img src={RedmiPhoto} width="100px" height="100px" alt="RedMi Photo" />, quantity: 0},
    {name: "Huawei", cost: 17, photo: <img src={HuaweiPhoto} width="100px" height="100px" alt="Huawei Photo" />, quantity: 0}
  ]); 

  const handleProductQuantityChange = ({ name, quantity }) => {
    const newProductList = [...productsData]
    const idx = productsData.findIdx(x => x.name === name);
    newProductList[idx].quantity = quantity
    setProductsData(newProductList)
  }

  const sum = productsData.reduce((result, {cost, quantity = 0}) => {
    result += quantity * cost
  }, 0)

  return (
    ...
    <div className="body-section">
      <div>Total: {sum}</div>
      {productsData.map((productData, i) => <ProductComponent key={i} name={productData.name} cost={productData.cost} photo={productData.photo} onQuantityChange={handleProductQuantityChange} />)}
      {/* <p><img src={iPhone} /></p> */}
    </div>
  )
}
function ProductComponent({ name, cost, photo, onQuantityChange }) {
  const increment = () => {
    setProdQuantity(prodQuantity + 1);
    onQuantityChange({ name, quantity: prodQuantity + 1 })
  };

  const decrement = () => {
    if(prodQuantity > 0) {
      setProdQuantity(prodQuantity - 1);
          onQuantityChange({ name, quantity: prodQuantity - 1 })
    }
  };
}