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
相关产品推荐
相关产品推荐

