1

I am trying to use "or" || operator in my render method of react like this (aim is to decide whether or not to show element)

<div className="item-actions">
    {this.state.addedMovieTag.filter(function( obj ) {
        return obj.trivia_id === item.id;
    }).length > 0 || this.state.addedPersonTag.filter(function( obj ) {
        return obj.trivia_id === item.id;
    }).length > 0  &&  <span className="fa fa-edit" onClick={this.saveChanges.bind(this, item)}></span>}
    <span className="fa fa-trash"></span>
</div>

now consider following scenarios (aim is to decide whether or not to show )

scenario 1: (span not shown)

this.state.addedMovieTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 0 
this.state.addedPersonTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 0

scenario 2: (span shows - expected behaviour)

this.state.addedMovieTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 1 
this.state.addedPersonTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 0

scenario 3: (span shows - expected behaviour)

this.state.addedMovieTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 2
this.state.addedPersonTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 0

scenario 4: (span not shows up - UNEXPECTED behaviour)

this.state.addedMovieTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 2
this.state.addedPersonTag.filter(function( obj ) {
    return obj.trivia_id === item.id;
}).length === 1
4
  • Your expression is: a || b || c && d. So is d associated with c? Yes. So if a or b is true, it will return true. but if c is false, it will not render d. Only case when d is rendered is if a and b is false and c is true. Try (a || b || c) && d instead Commented Apr 19, 2018 at 10:23
  • Possibly some logical operator precedence fault where a || b && c is different from (a || b) && c (being the latter what you desire)? Also, I would recommend moving that logic out from the view and assign it to a variable so it leaves the view to rendering only with an easy-to-read simple logic e.g. {hasContentToDisplay && <span ...>} Commented Apr 19, 2018 at 10:25
  • @mathielo Thanks a lot. Rookie mistake from my side Commented Apr 19, 2018 at 10:27
  • A bit unrelated, but you may want to consider using the .some() function if you're checking for length > 0 after a filter(). Commented Apr 19, 2018 at 10:27

2 Answers 2

1

As logical expressions are evaluated left to right, they are tested for possible "short-circuit" evaluation using the following rules:

false && (anything) is short-circuit evaluated to false.

true || (anything) is short-circuit evaluated to true.

So you should wrap all conditions into bracket and use ||

<div className="item-actions">
    { (this.state.addedMovieTag.filter(function( obj ) {
        return obj.trivia_id === item.id;
    }).length > 0 || this.state.addedPersonTag.filter(function( obj ) {
        return obj.trivia_id === item.id;
    }).length > 0 ) &&  <span className="fa fa-edit" onClick={this.saveChanges.bind(this, item)}></span>}
    <span className="fa fa-trash"></span>
</div>
Sign up to request clarification or add additional context in comments.

Comments

0

I think this has to do with the short circuit evaluation ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Logical ) and could be simply fixed by placing the OR check in brackets.

You could try typing in browser console:

true || true && false //will return true
(true || true) && false //will return false

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.