React中如何实现单次点击触发onClick绑定逻辑执行三次
问题根因
你的代码失效是由React的两个机制共同导致的:
- 同一个事件回调内的多次state更新会被React批处理,不会立刻触发重渲染
- 你的回调捕获的是当前渲染周期的
cartItems快照,所有setCartItems调用都是基于同一个旧值修改,后续更新会直接覆盖前面的修改结果,最终仅最后一次更新生效
实现方案
方案1:一次性计算后更新(推荐)
先在内存中完成3次随机商品的添加逻辑,最后仅调用一次state更新,无冲突且性能更好:
const onRandom = () => { // 复制当前购物车作为临时修改对象 let newCart = [...cartItems]; // 循环3次添加随机商品 for (let i = 0; i < 3; i++) { const randomItem = products[Math.floor(Math.random() * products.length)]; const existItem = newCart.find(item => item.id === randomItem.id); if (existItem) { existItem.qty += 1; } else { newCart.push({...randomItem, qty: 1}); } } // 一次性更新state setCartItems(newCart); };
方案2:使用函数式state更新
如果需要拆分添加逻辑,可以用setState的函数式参数,每次更新都基于上一次的最新state值计算:
// 封装添加单个随机商品的逻辑 const addSingleRandom = () => { setCartItems(prevCart => { const randomItem = products[Math.floor(Math.random() * products.length)]; const existItem = prevCart.find(item => item.id === randomItem.id); if (existItem) { return prevCart.map(item => item.id === randomItem.id ? {...existItem, qty: existItem.qty + 1} : item ); } else { return [...prevCart, {...randomItem, qty: 1}]; } }); }; const onRandom = () => { // 连续调用3次即可 addSingleRandom(); addSingleRandom(); addSingleRandom(); };
函数式更新的入参prevCart永远是上一次更新后的最新state值,不会出现更新覆盖问题。
内容的提问来源于stack exchange,提问作者Elias
相关产品推荐
相关产品推荐

