大家好,我有一个这样的数组:
[
{
"name": "test",
"amount": 794.651786,
"id": "60477897fd230655b337a1e6"
},
{
"name": "test2",
"amount": 10.80918,
"id": "60477bfbfd230655b337a1e9"
}
]
我不想把每笔钱都加起来。
我尝试像这样使用useState钩子:
const [total, setTotal] = useState(Number);
array.map((item) => {
setTotal(total + item.amount);
});
但是它似乎没有像预期的那样工作。
您可以使用reduce方法,参见docs。
setTotal(array.reduce((sum, item) => sum + item.amount, 0))
我邀请你阅读这个JavaScript: . foreach()和。map()之间的区别。你不应该这样使用.map
。对于这个用例,使用.forEach
代替。
您可能希望使用最少的调用来更新状态。首先,我要这样做:
let _total = 0;
array.forEach((item) => {
_total += item.amount;
});
setTotal(_total);
也就是说,您只需要如果array
已经改变,执行此操作。假设数组是一个道具,这可以很容易地完成useEffect
钩子:
useEffect(()=>{
let _total = 0;
array.forEach((item) => {
_total += item.amount;
});
setTotal(_total);
},[array]);
希望这能帮助您全面了解最佳实践是什么。你还可以查看钩子的规则,以便更好地理解在哪里调用setState
我的评论没有得到解决,但我将添加一个答案来解决我的问题-total
根本不应该处于状态。
total
很可能不是状态——它是计算状态——也就是说,它是从其他状态和/或道具派生的。
如果是这种情况(99%是这样),那么将total设置为状态是不正确的,这只会导致更多的代码和更复杂的调试:
例子:
当数据源为prop时:
const Cart = ({someItemsInMyCart}) => {
const total = useMemo(() => someItemsInMyCart.reduce((acc,item) => acc+item.amount,0),[someItemsInMyCart]);
return (/* some JSX */);
}
当数据源为状态时:
const Cart = () => {
const [items,setItems] = useState([]);
const total = useMemo(() => items.reduce((acc,item) => acc+item.amount,0),[items]);
return (/* some JSX */);
}
你可以写上面的两个例子,完全省略useMemo
,这只是一个性能优化,因为以这种方式减少数组是相当快的,除非你处理的是1000个项目。
试试这个
const [total, setTotal] = useState(0);
array.map((item) => {
setTotal(prevCount => prevCount + item.amount);
});