React中使用useState设置数组为空不生效的问题如何解决?
分类切换时商品列表清空不生效问题分析
问题原因
- React 状态更新为异步批量执行机制:在同一个 useEffect 执行上下文中,连续调用
setShownMenuItems时,当前作用域内的shownMenuItems始终是本次 useEffect 触发时的旧值,不会因为前面调用了setShownMenuItems([])就立刻变为空数组。 - 原有代码在循环中使用
[...shownMenuItems, menuItem]生成新数组,每次获取的都是初始旧值,多次状态更新会被批量合并,最终仅最后一次更新生效,导致清空操作看起来没有生效。
解决方案
方案1:使用函数式状态更新
函数式更新的入参 prev 永远是上一次状态更新后的最新值,不受当前作用域旧状态的影响,可以保证每次累加的结果正确:
useEffect(() => { setShownMenuItems([]) if(categoryId===""){ setShownMenuItems(menuItems) }else{ menuItems.forEach(menuItem=>{ if(menuItem.categoryId === categoryId){ setShownMenuItems(prev=>[...prev, menuItem]) } }) } }, [categoryId, menuItems])
注意:需要把
menuItems加入 useEffect 的依赖数组,避免全量商品更新后分类筛选不生效的问题。
方案2:更简洁的过滤写法(推荐)
无需手动清空列表,也无需循环多次调用状态更新,直接将过滤后的结果赋值给 shownMenuItems 即可,性能和可读性都更高:
useEffect(() => { if(categoryId === ""){ setShownMenuItems(menuItems) }else{ const filteredMenu = menuItems.filter(item => item.categoryId === categoryId) setShownMenuItems(filteredMenu) } }, [categoryId, menuItems])
内容的提问来源于stack exchange,提问作者Mithat Akbulut
相关产品推荐
相关产品推荐

