Next.js修改组件列表后旧组件值变为undefined问题求助
React表格总价计算Bug修复:多行时旧项值变为undefined
我遇到一个困扰了一周的Bug:在React表格中,每行对应一个产品列表项。当修改数量或价格时,最后一列的总价会更新并同步到待提交后端的列表中。控制台打印newList显示最后一项总价可正常添加到列表,但当列表项超过2个时,之前的旧项值会变为undefined。
原组件代码:
function CountTotalPrice({ data, setListProductImport, listProductImport, setNewList, }) { const [price, setPrice] = useState<any>() const handleSetPrice = () => { const list = listProductImport const newList = list.map((item) => { if (item.productId == data.productId) { const totalPrice = new BigNumber(item.amount).multipliedBy( item.costPrice, ) const discountPrice = new BigNumber(item.amount) .multipliedBy(item.costPrice) .multipliedBy(item.discount) .dividedBy(100) if (item.discount) { const afterPrice = totalPrice.minus(discountPrice) setPrice(afterPrice) } else { setPrice(totalPrice) } } return item }) } useEffect(() => { handleSetPrice() }, [listProductImport]) useEffect(() => { if (price) { const list = listProductImport const newList = list.map((item) => { if (item.productId === data.productId) { return { ...item, price: price.toFixed() } } return item }) console.log("newList", newList) setNewList(newList) } }, [price]) return ( <div className="py-2 text-center text-white rounded-md cursor-pointer bg-successBtn"> {new BigNumber(price).toFormat(0)} đ </div> ) }
问题分析与修复
核心问题
- 多实例状态冲突:每个
CountTotalPrice组件都维护独立的price状态,当列表项超过2个时,未被更新的组件实例中price仍为undefined,渲染时触发错误导致旧项值异常。 - 冗余状态中转:通过
price状态间接更新列表的逻辑,会导致多轮状态更新,引发数据同步不一致。 - 缺乏空值防护:未处理
price为undefined时的渲染逻辑,直接调用new BigNumber(price)会抛出错误。
修复后的代码
function CountTotalPrice({ data, listProductImport, setNewList, }) { // 直接计算当前行的总价,无需组件内部状态维护 const getTotalPrice = () => { const currentItem = listProductImport.find(item => item.productId === data.productId); if (!currentItem) return new BigNumber(0); let total = new BigNumber(currentItem.amount).multipliedBy(currentItem.costPrice); if (currentItem.discount) { const discount = total.multipliedBy(currentItem.discount).dividedBy(100); total = total.minus(discount); } return total; }; const totalPrice = getTotalPrice(); // 直接根据计算结果更新列表,去掉冗余状态中转 useEffect(() => { const updatedList = listProductImport.map(item => item.productId === data.productId ? { ...item, price: totalPrice.toFixed() } : item ); setNewList(updatedList); }, [listProductImport, totalPrice, setNewList, data.productId]); return ( <div className="py-2 text-center text-white rounded-md cursor-pointer bg-successBtn"> {totalPrice.toFormat(0)} đ </div> ); }
修复要点
- 移除内部
price状态:直接通过函数计算当前行总价,避免多组件实例间的状态干扰。 - 简化更新逻辑:在
useEffect中直接用计算结果更新列表,减少不必要的状态流转。 - 增加空值判断:通过
find确保找到当前行数据,兜底返回0避免计算错误。 - 明确依赖数组:完善
useEffect的依赖项,确保更新时机准确。
内容的提问来源于stack exchange,提问作者Mohtep
相关产品推荐
相关产品推荐

