0

I've got this small bit of JS code which I'm sure was working but seems to have stopped:

if(currentUser && currentUser._id === shinyItem.author.id || currentUser && currentUser.isAdmin) {
 <p>Hello banana</p>
}

The problem seems to be this part:

currentUser._id === shinyItem.author.id

If I console.log both those values are the same, so it should be working. However, if I remove it and run this code it works just fine:

if(currentUser || currentUser && currentUser.isAdmin) {
  <p>Hello banana</p>
}

It's probably something painfully obvious, any help appreciated.

5
  • "those values are the same" well, they are probably not. Commented Feb 27, 2020 at 6:40
  • 3
    Please use () when you mix && and ||. The order of execution can be confusing when you look at this code. Commented Feb 27, 2020 at 6:41
  • 4
    Can you ensure type of those values? Like are both of type ObjectId or string? Commented Feb 27, 2020 at 6:41
  • Please add the shinyItem and currentUser objects. Need to know whats inside. Adding a code snippet would be much appreciable to fix the issue. Also have you tried without checking the type ? means '==' instead of '===' Commented Feb 27, 2020 at 6:41
  • This is not valid syntax. This could never have worked. Commented Nov 6 at 8:56

5 Answers 5

2

Just because they log the same value doesn't mean they're of the same type.

You're using the strict equality operator (===) and values of differing type will be considered unequal.

You can try using the loose equality operator (==) to see if you get your expected result. Alternatively, you can perform explicit type conversion to ensure you're dealing with matching types.

To illustrate:

numberValue = 12345;
stringValue = '12345';

console.log('numberValue: ' + numberValue);
console.log('stringValue: ' + stringValue);
console.log('typeof numberValue: ' + (typeof numberValue));
console.log('typeof stringValue: ' + (typeof stringValue));
console.log('numberValue === stringValue: ' + (numberValue === stringValue));
console.log('numberValue == stringValue: ' + (numberValue == stringValue));
console.log('numberValue === parseInt(stringValue, 10): ' + (numberValue === parseInt(stringValue, 10)));


Also, a simpler way to express your conditional statement would be:

if (currentUser && (currentUser._id === shinyItem.author.id || currentUser.isAdmin)) {
Sign up to request clarification or add additional context in comments.

1 Comment

This is better, you don't have to check currentUser twice.
2

If currentUser.isAdmin is falsey, but currentUser._id looks to log the same thing as shinyItem.author.id, it must be that they aren't actually the same value. Either the type of one is different from the other (such as if one is of type string and the other is of type number), or the difference can't be easily seen visually, such as if one has a trailing space or few, or has a similar-looking character (eg 1 the number and l the letter), or one may have a zero-width character that the other lacks, or something like that.

Double check the values in both variables. It's clear that something is different between them. If both are strings and you still don't see a difference, you can examine the character code of each index of the string to find the difference eg:

const str1 = 'foo\u200bbar';
const str2 = 'foobar';
console.log(str1);
console.log(str2);
// They look the same when logged, but...
for (let i = 0; i < str1.length; i++) {
  if (str1[i] !== str2[i]) {
    console.log(`Found difference at index ${i}: code ${str1[i].charCodeAt()} !== code ${str2[i].charCodeAt()}`);
    break;
  }
}

Comments

1

Add parentheses.

if ((currentUser && (currentUser._id === shinyItem.author.id)) || (currentUser && currentUser.isAdmin)) {
  return <p>Hello banana</p>;
}

Comments

0

I've found the answer. I though if I use only == it would sort it but that also results in falsey so it still didn't work.

I then did some more digging and found this post stackoverflow.com/questions/11637353/… which seems to solve my problem. What I didn't understand was that the contents of currentUser._id is a custom mongoDB object ID type. To resolve I needed to use the mongodb function .equals() like this:

if(currentUser && currentUser._id.equals(shinyItem.author.id) || currentUser && currentUser.isAdmin) {

Comments

0

Strict comparison === means that both type and value must be the same to return true as result. The reason, both those currentUser._id and shinyItem.author.id look the same, is that they might be used in a context, where javascript engine tries to implement type coercion. If currentUser._id is mongoose ObjectID, it has toString method in it, and javascript engine will use it while implementing type coercion and returns a string:

// log id is 5e59d4dfe93451416fc551db, instead of 
// log id is ObjectID {_bsontype: "ObjectID", id: Buffer(12)}
console.log(`id is ${currentUser._id}`); 

So using strict comparison between ObjectID and string resolves to false:

// value is the     value is the 
// same, but type   same, but type 
// is ObjectID      is string
currentUser._id === shinyItem.author.id // false

But loose equality comparison == resolves to true, because, behind the scene, javascript engine tries to coerce both values to the same type (string), using toString method of ObjectID and converting it to the string:

currentUser._id == shinyItem.author.id // true

Mongoose also has id virtual getter, which returns the documents _id field cast to a string, so you can use it like this (if you did not disable it in schema):

// id is a string
currentUser.id === shinyItem.author.id // true

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.