You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS搜索对象数组时去重后状态不更新问题求助

问题分析

你的代码核心问题在于React状态更新是异步的,在forEach循环里多次调用setSearchedArray时,每次读取到的searchedArray都是当前渲染周期的旧值,不是实时更新后的状态。这就导致你最后设置的pp其实是基于旧状态处理的,自然无法正确同步到最终的状态中。

另外,你的逻辑完全可以简化——不需要先清空、循环添加再去重,直接一步完成匹配+去重的操作,再一次性更新状态即可。

修正方案

直接先筛选出所有匹配搜索关键词的项,再对结果去重,最后一次性设置状态:

useEffect(() => {
  // 1. 先筛选出名称匹配的项
  const matchedItems = allItems.filter(item => 
    item.name.toUpperCase().includes(searchText.toUpperCase())
  );
  
  // 2. 基于id去重,用Map高效处理重复项
  const uniqueItems = Array.from(new Map(matchedItems.map(item => [item.id, item])).values());
  
  // 3. 一次性更新状态
  setSearchedArray(uniqueItems);
}, [searchText, allItems]);

代码说明:

  • 用filter直接筛选所有匹配项,替代原来的forEach循环,逻辑更简洁直观。
  • 用Map实现去重:将每个item的id作为唯一key,相同id的item会被自动覆盖,最后提取Map的values就能得到去重后的数组,比filter+findIndex的方式性能更优(数据量大时差异更明显)。
  • 依赖数组添加allItems,确保源数据变化时也能重新计算搜索结果(如果allItems是状态或props的话)。
原代码失效原因

举个实际场景:第一次循环匹配到itemA,调用setSearchedArray([...searchedArray, itemA]),但此时searchedArray还是初始空数组,状态会被设为[itemA],但更新不会立刻生效。第二次循环匹配到itemB时,读取到的searchedArray依然是空数组,所以[...searchedArray, itemB]还是[itemB],直接覆盖了之前的更新,后续去重逻辑也基于空数组处理,自然得不到正确结果。

内容的提问来源于stack exchange,提问作者Sabih Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 18:21:27