React组件更新时数组重复添加,!includes校验失效问题求助
问题原因与解决方案
核心问题分析
- 直接修改React State:你用
searchResults.push(data)直接修改了state数组,React的state是不可变的,这种修改不会触发组件重新渲染,后续的state更新还会覆盖这种无效修改。 - 对象引用导致去重失效:
Array.includes()对对象采用引用比较,从Firebase返回的每个doc.data()都是新创建的对象,哪怕内容完全一致,引用地址也不同,所以!searchResults.includes(data)永远为true,去重逻辑完全失效。 - 闭包捕获旧state:你的
useEffect依赖是空数组,里面捕获的searchResults是组件初始渲染时的空数组,所以每次遍历都会执行push操作。
修复后的代码
const Directory = () => { const [searchResults, setSearchResults] = useState([]); const [loading, setLoading] = useState(false); const { currentUser } = useContext(AuthContext); useEffect(() => { setLoading(true); const fetchDoctors = async () => { const q = query(collection(db, "users"), where("type", "==", "doctor")); const querySnapshot = await getDocs(q); // 整理数据,把Firebase文档的唯一id加入对象,作为去重标识 const newDoctors = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // 用函数式更新state,基于最新的state做去重 setSearchResults(prevResults => { // 过滤掉已存在的医生(通过id判断) const uniqueNewDoctors = newDoctors.filter(newDoc => !prevResults.some(existingDoc => existingDoc.id === newDoc.id) ); // 合并旧数组和去重后的新数组 return [...prevResults, ...uniqueNewDoctors]; }); setLoading(false); }; fetchDoctors(); }, []); console.log(searchResults); // 其他组件逻辑... };
关键修复点
- 函数式更新state:
setSearchResults(prevResults => ...)确保每次更新都基于最新的state值,避开闭包问题。 - 基于唯一标识去重:用Firebase文档的
doc.id作为判断依据,通过prevResults.some()检查是否已存在,解决对象引用比较的问题。 - 遵循state不可变原则:通过展开运算符创建新数组,不直接修改原state。
内容的提问来源于stack exchange,提问作者Jacqueline
相关产品推荐
相关产品推荐

