数组含目标对象时includes()返回false的问题排查
为什么includes()检查对象数组时返回false?
问题根源
JavaScript中对象属于引用类型,includes()方法使用**严格相等(===)**进行比较。只有当两个对象指向内存中的同一地址时,===才会返回true。你从Firestore获取的badge.data()是每次调用都会生成的新对象,即使它和userData.obtainedBadges里的对象内容完全一致,二者的内存引用也是不同的,所以includes()会返回false。
另外你的代码还有一个隐性问题:querySnapshot.forEach()中使用async回调是无效的——forEach不会等待异步函数执行完成,会导致setObtainableBadges和setUserBadges的状态更新逻辑混乱。
解决方案
1. 用some()替代includes(),基于唯一标识判断
利用对象的唯一属性(比如id)来判断是否存在,避免引用比较的问题:
2. 替换forEach为for...of,正确处理异步逻辑
修改后的完整代码:
const querySnapshot = await getDocs(colRef); // 用for...of遍历,支持async/await的顺序执行 for (const badgeDoc of querySnapshot.docs) { const badgeData = badgeDoc.data(); console.log(userData.obtainedBadges); // 通过id判断用户是否已拥有该徽章 const isBadgeOwned = userData.obtainedBadges.some(ownedBadge => ownedBadge.id === badgeData.id); if (!isBadgeOwned) { console.log(badgeData); console.log("not includes"); setObtainableBadges(prev => [...prev, badgeData]); } else { console.log("includes"); setUserBadges(prev => [...prev, badgeData]); } }
说明
some()方法会遍历数组,只要有一个元素满足ownedBadge.id === badgeData.id就返回true,通过唯一标识的数值比较,避开了对象引用的问题。for...of循环可以配合async/await使用,确保每个迭代的逻辑执行完成后再处理下一个,避免状态更新的竞态问题。
内容的提问来源于stack exchange,提问作者Jaydendev
相关产品推荐
相关产品推荐

