Use a Ternary Expression for Conditional Rendering - Why does this work?

I don’t understand why this ternary operator works. It seems like the first operator should reduce the overall statement to either:

buttonTwo ? buttonOne : buttonThree

OR

true ? buttonOne : buttonThree

In either case it seems like buttonOne and buttonThree should be the only options for what is actually rendered to the screen, so why is it that when the condition userAge >= 18 is true, buttonTwo is rendered seemingly without evaluation the second ternary expression?




const inputStyle = {
  width: 235,
  margin: 5
}

class CheckUserAge extends React.Component {
  constructor(props) {
    super(props);
    // change code below this line
    this.state = {
      input: '',
      userAge: ''
    }
    // change code above this line
    this.submit = this.submit.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(e) {
    this.setState({
      input: e.target.value,
      userAge: ''
    });
  }
  submit() {
    this.setState({
      userAge: this.state.input
    });
  }
  render() {
    const buttonOne = <button onClick={this.submit}>Submit</button>;
    const buttonTwo = <button>You May Enter</button>;
    const buttonThree = <button>You Shall Not Pass</button>;
    return (
      <div>
        <h3>Enter Your Age to Continue</h3>
        <input
          style={inputStyle}
          type="number"
          value={this.state.input}
          onChange={this.handleChange} /><br />
        {
          /* change code here */
          (this.state.userAge >= 18) ? buttonTwo : (this.state.userAge=='') ? buttonOne : buttonThree
        }
      </div>
    );
  }
};

I haven’t gotten into React yet, but I did use ternary operators a bunch of times. It makes sense that second expression wouldn’t be evaluated if the first one is true; that’s how ternary operators work. Your statements translate to this:

if (this.state.userAge >= 18) {
   render buttonTwo;
} else {
  if (this.state.userAge=='') {
    render buttonOne;
  } else {
    render buttonThree;
  }
}

Thanks, I guess it makes sense when you structure it in the if/else format, just feels odd because the entire first operator seems to serve as the ‘condition’ for the second statement, as if you were plugging a variable into a math problem.

But there is a difference between if/else and ternary. The if/else just branches off and executes different statements. But a ternary evaluates to the value it returns. This is an important distinction and is what allows us to use the ternary in JSX. For example, if I have:

<div>
  <Text>{ (age >=21) ? 'Have a beer!' : 'Have a soda!' }</Text>
</div>

If the age is 35, then that ternary will evaluate to 'Have a beer!'. If/else can’t do that. Now, you could optionally, before the JSX, done something like:

let message;
if (age >=21)
  message = 'Have a beer!';
else
  message = 'Have a soda!';

and then in your JSX,

<div>
  <Text>{ message }</Text>
</div>

of course, ternaries would work in the JS too:

const message = (age >=21) ? 'Have a beer!' : 'Have a soda!';

You will see a lot of ternary operators in JSX for simple selection like in the example. Similarly you will see a lot of short-circuited && and ||.

Everything looks weird until you get used to it.