Im receving some products on props in the OrderContent component to use them in a select component, when I select the product in the select it renders Summary and Product components, in those components I can choose the quantity and with that I can calculate the total all back on the OrderContent Component, the problem is when im trying to use the OnChange in the input type (on Product component), useEffect (inside is the function that calculates the total in the state) doesnt trigger but it does if I add a product from the state or remove it.
import React, { Fragment, useState, useEffect } from "react";
import Select from "react-select";
import Animated from "react-select/lib/animated";
import Summary from './Summary';
function OrderContent({ products }) {
const [productsSelected,setProductsSelected] = useState([]);
const [total,setTotal] = useState(0);
useEffect(() => {
updateTotal()
}, [productsSelected]);
const selectProduct = (prod)=>{
setProductsSelected(prod)
}
const updateQuantity = (val,index)=>{
const tempProds = productsSelected;
tempProds[index].quantity= Number(val);
setProductsSelected(tempProds)
}
const deleteProduct = (id) =>{
const tempProds = productsSelected;
const remProds = tempProds.filter((p)=> p.id !== id );
setProductsSelected(remProds);
}
const updateTotal = () =>{
const tempProds = productsSelected;
if(tempProds.length === 0){
setTotal(0)
return;
}
let newTotal = 0;
tempProds.map((p)=>{
const q = p.quantity ? p.quantity : 0;
newTotal = newTotal + (q * p.price)
})
setTotal(newTotal)
}
return (
<Fragment>
<h2 className="text-center mb-5">Select Products</h2>
<Select
onChange={selectProduct}
options={products}
isMulti={true}
components={Animated()}
placeholder={"Select products"}
getOptionValue={options => options.id}
getOptionLabel={options => options.name}
value={productsSelected}
/>
<Summary
products={productsSelected}
updateQuantity={updateQuantity}
deleteProduct = {deleteProduct}
/>
<p className="font-weight-bold float-right mt-3">
Total:
<span className="font-weight-normal">
${total}
</span>
</p>
</Fragment>
);
}
export default OrderContent;
import React, {Fragment} from 'react';
import Product from './Product';
function Summary({products,updateQuantity,deleteProduct}) {
if(products.length === 0) return null;
return (
<Fragment>
<h2 className="text-center my-5">Summary and Quantities</h2>
<table className="table">
<thead className="bg-success text-light">
<tr className="font-weight-bold">
<th>Product</th>
<th>Price</th>
<th>Inventory</th>
<th>Quantity</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{products.map((p,index)=>{
return (<Product
key={p.id}
id={p.id}
product={p}
index={index}
updateQuantity={updateQuantity}
deleteProduct={deleteProduct}
/>)
})}
</tbody>
</table>
</Fragment>
)
}
export default Summary
import React, { Fragment } from "react";
function Product({ product, updateQuantity, index, deleteProduct }) {
return (
<Fragment>
<tr>
<td>{product.name}</td>
<td>${product.price}</td>
<td>{product.stock}</td>
<td>
<input
type="number"
className="form-control"
onChange={e => updateQuantity(e.target.value, index)}
/>
</td>
<td>
<button type="button" className="btn btn-danger font-weight-bold" onClick={e=> deleteProduct(product.id)}>
× Delete
</button>
</td>
</tr>
</Fragment>
);
}
export default Product;