Reputation: 163
I have an array with objects inside. I get the array from my firestore database.
When I get the array, I check if my user has any of the objects. When I check this using includes()
I get false as a return, but the array clearly has the object. What can be the issue?
Check:
const querySnapshot = await getDocs(colRef);
querySnapshot.forEach(async(badge) => {
console.log(userData.obtainedBadges)
if(!userData.obtainedBadges.includes(badge.data())){
console.log(badge.data())
console.log("not includes")
setObtainableBadges(prev => {
return [...prev, badge.data()]
})
} else {
console.log("includes")
setUserBadges(prev => {
return [...prev, badge.data()]
})
}
})
For example one of the objects I check( badge.data()
) :
Object { id: 1, desc: "Play 5 games.", type: "games", reward: 10, condition: 5, img: "/trophies/firsttrophy.png", name: "The First Games" }
querySnapshot
Array:
Array(9) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…} ]
0: Object { img: "/trophies/firsttrophy.png", type: "games", name: "The First Games", … }
1: Object { id: 2, type: "games", name: "The Beginner", … }
2: Object { name: "The Big Brain", id: 50, type: "games", … }
3: Object { condition: 50, id: 4, desc: "Play 50 games.", … }
4: Object { name: "Noob", reward: 10, img: "/trophies/noobmedal.png", … }
5: Object { id: 6, reward: 10, desc: "Reach a minimum high score of 2000.", … }
6: Object { condition: 3000, desc: "Reach a high score of 3000.", name: "Unstoppable", … }
7: Object { desc: "Reach a score of 0 in any gamemode.", id: 9, reward: 25, … }
8: Object { type: "easteregg", condition: "easteregg", desc: "Find an easter egg!", … }
length: 9
<prototype>: Array []
You can see, that my object is the first element in the array. But for some reason, includes()
returns false.
Upvotes: 1
Views: 1696
Reputation: 76464
includes searches a value inside an object. Yet, similar objects are not the same, just like twins are different persons. Proof:
console.log({} === {});
So, since includes
does not search for similar objects, but for the specific object, your
if (!userData.obtainedBadges.includes(badge.data())) {
is incorrect. Instead, you will need to .filter()
yourself, like:
if (userData.obtainedBadges.filter(item => item.id === badge.data().id).length === 0) {
Which searches a match for badge.data()
inside userData.obtainedBadges
by id
, retrieves an array, whose size is 0 if no such match was found.
Upvotes: 0
Reputation: 1
I just fixed it by my own function instead of .includes():
function areIdentical(actualValue, expectedValue) {
let actualValueKeys = Object.keys(actualValue);
let expectedValueKeys = Object.keys(expectedValue);
if (actualValueKeys.length != expectedValueKeys.length) {
return 0;
} else {
let result = 0;
actualValueKeys.forEach(x => {
if (actualValue[x] == expectedValue[x]) result += (1 / actualValueKeys.length) * 100;
});
return result;
}
}
and You can use:
(yourArray.filter(x => areIdentical(x, value) > 99).length > 0) ? true : false
Upvotes: -1
Reputation: 1346
When you compare two objects in JavaScript it is not enough that their keys and values match. All objects have internal ids and therefor two objects or arrays with the same keys and values will in a regular comparison like == still return false. See example :
const object1 = {test:'test'}
const object2 = {test:'test'}
console.log(object1 == object2)
const badge_in_user_data = userData.obtainedBadges.some(badge => badge.id == badge.data().id)
Upvotes: 2