Javascript onChange未触发useEffect
我在OrderContent组件中收到一些道具上的产品,以便在select组件中使用它们,当我在select it renders Summary和product components中选择产品时,我可以在这些组件中选择数量,并使用这些数量计算OrderContent组件上的全部总数,问题是,当我尝试在输入类型(产品组件)中使用OnChange时,useffect(内部是计算状态中的总数的函数)不会触发,但如果我从状态中添加或删除产品,它会触发Javascript onChange未触发useEffect,javascript,reactjs,Javascript,Reactjs,我在OrderContent组件中收到一些道具上的产品,以便在select组件中使用它们,当我在select it renders Summary和product components中选择产品时,我可以在这些组件中选择数量,并使用这些数量计算OrderContent组件上的全部总数,问题是,当我尝试在输入类型(产品组件)中使用OnChange时,useffect(内部是计算状态中的总数的函数)不会触发,但如果我从状态中添加或删除产品,它会触发 import React, { Fragment,
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;
import React,{Fragment,useState,useffect}来自“React”;
从“反应选择”导入选择;
从“react select/lib/Animated”导入动画;
从“./Summary”导入摘要;
函数OrderContent({products}){
常量[productsSelected,setProductsSelected]=useState([]);
const[total,setTotal]=useState(0);
useffect(()=>{
updateTotal()
},[所选产品];
const selectProduct=(prod)=>{
已选择设置产品(产品)
}
常量updateQuantity=(val,index)=>{
const tempProds=已选择的产品;
临时产品[索引]。数量=数量(val);
已选择设置产品(临时产品)
}
常量deleteProduct=(id)=>{
const tempProds=已选择的产品;
const remProds=tempProds.filter((p)=>p.id!==id);
选择设置产品(remProds);
}
const updateTotal=()=>{
const tempProds=已选择的产品;
如果(tempProds.length==0){
setTotal(0)
返回;
}
设newTotal=0;
临时产品映射((p)=>{
常数q=p.数量?p.数量:0;
新总计=新总计+(q*p.价格)
})
setTotal(新总数)
}
返回(
精选产品
options.id}
getOptionLabel={options=>options.name}
值={productsSelected}
/>
总数:
${total}
);
}
导出默认订单内容;
从“React”导入React,{Fragment};
从“./产品”导入产品;
函数摘要({products,updatequality,deleteProduct}){
if(products.length==0)返回null;
返回(
摘要和数量
产品
价格
库存
量
删除
{products.map((p,index)=>{
返回()
})}
)
}
导出默认摘要
从“React”导入React,{Fragment};
函数乘积({Product,updatequality,index,deleteProduct}){
返回(
{product.name}
${product.price}
{product.stock}
updateQuantity(e.target.value,index)}
/>
deleteProduct(product.id)}>
&时间;删除
);
}
导出默认产品;
updateQuantity
处于变异状态。这意味着react将看到您尝试使用相同的对象引用更新状态,并且将跳过重新渲染,这意味着没有useffect
触发器
将其更改为此以使用新嵌套对象创建新阵列:
const updatequality=(val,index)=>{
const tempProds=[…productsSelected.map(val=>{…val})];
临时产品[索引]。数量=数量(val);
已选择设置产品(临时产品)
}
deleteProduct
不会变异,因为filter
返回一个新数组。但是设置temprods
是完全没有必要的
updateTotal
也会改变状态,但只会改变其嵌套对象。因此,这仍然需要修复,但可能不会导致相同的重新渲染问题
基于在多个地方使用了
const tempProds=products selected
,我认为您应该研究一下如何分配和引用JavaScript对象。有很多资源,但我写了一个相当详细的解释作为其中的一部分。如果选择的产品是同一个数组,那么useEffect无法检测到更改,因为它总是指向同一个对象
const selectProduct = (prod)=>{
setProductsSelected([...prod])
}
强制所选产品成为新阵列谢谢!它的工作,我也会阅读你给我的答案。