François Richard
François Richard

Reputation: 7045

javascript ternary operator "chaining"

I'm trying to write something like this with a ternary operator (needed because of jsx syntax constraints)

if(!this.state.msg) {
    if(this.state.ask.length != 0) {
        // do stuff
    } else {
       // do stuff
    }
    if(this....) {
        //do stuff
    } else {
      // ...
    }
} else {
    //nothing
}

So I tried this dumb

   !this.state.msg ? this.state.ask.length != 0 ? //do stuff : "" this.state... ? //do stuff : //do other stuff : //nothing

But it's obviously not the right way to go.

Any help very welcomed. thanks in advance.

Upvotes: 5

Views: 6087

Answers (5)

user663031
user663031

Reputation:

Your true branch has two components; you can separate them with commas (parenthesized, since the comma has weaker associativity than the ternary operator). So

!this.state.msg ?
  (
    this.state.ask.length != 0 ? /*stuff*/ : /*stuff*/,
    this... ? /* stuff */ : /* ... */
  ) : /* nothing */

Or, since the else branch is doing "nothing", you could replace the ternary operator at the top level with a simple and:

!this.state.msg &&
  (
    this.state.ask.length != 0 ? /*stuff*/ : /*stuff*/,
    this... ? /* stuff */ : /* ... */
  )

Upvotes: 5

Dan Prince
Dan Prince

Reputation: 29989

Maybe it'd help to add another perspective. It's very rare that you would actually need to use the ternary operator with JSX. In this case, I would consider moving all of this logic out into a separate function.

helperFunction: function() {
  if(!this.state.msg) {
    if(this.state.ask.length != 0) {
      // return stuff
    } else {
      // return stuff
    }

    if(this....) {
      // return stuff
    } else {
      // ...
    }
  } else {
    // nothing
  }
}

Then you'd be able to use your helper function from inside your render method.

React.createClass({
  helperFunction: function() {
    // ...
  },
  render: function() {
    return (
      <div>
       {this.helperFunction()}
      </div>
    );
  }
});

Your helper function can return values that can be used for attributes, or it can return other JSX components. Often I find it helpful to move code out of patterns that look like this:

render: function() {
  return (
    condition === 'example' ?
      <MyComponent attr={this.props.example} onChange={this.props.onChange} /> :
      <MyOtherComponent attr={this.state.example} onChange={this.state.onChange}/>
   );
}

To code that looks like this:

helper: function(condition) {
  if(condition === 'example') {
    return (
      <MyComponent attr={this.props.example} onChange={this.props.onChange} />
    );
  }

  else {
    return (
      <MyOtherComponent attr={this.state.example} onChange={this.state.onChange}/>
    );
  }
},
render: function() {
  return this.helper(condition);
}

Or even better in the case of string equality checking.

helper: function(condition) {
  const default = <MyOtherComponent attr={this.state.example} onChange={this.state.onChange}/>

  const conditions = {
    example: <MyComponent attr={this.props.example} onChange={this.props.onChange} />,
    example2: <MyComponent attr={this.props.example} onChange={this.props.onChange} />,
    example3: <MyComponent attr={this.props.example} onChange={this.props.onChange} />,
  };

  return conditions[condition] || default;
},
render: function() {
  return this.helper(condition);
}

This way gives you most of the power of a switch statement, but terser syntax too, it lets you elegantly select from a large number of conditional components. The same code written with if statements (regular or ternary) would be much more verbose.

Upvotes: 3

JsingH
JsingH

Reputation: 189

For verbosity, clarity of expression and maintainability, I would not recommend converting if-else to ternary expression. Try to keep your code simple even at the expense of few extra lines.

Here it is if you just want to learn

!this.state.msg ? 
  (this.state.ask.length != 0 ? //do if stuff : //do else stuff),
  (this.some == 0 ? //do 2nd if stuff : //do 2nd else stuff)
:

Upvotes: 1

rollingBalls
rollingBalls

Reputation: 1878

You are wrong in your assertion that JSX limits you in this way - read this doc page and you will see that you can use something like this:

{(() => {
// My awesome multi-step code
})()}

Upvotes: 4

Casey ScriptFu Pharr
Casey ScriptFu Pharr

Reputation: 1670

Visualizing it helps.

    !this.state.msg ?
                        ? this.state.ask.length != 0) 
                              // do stuff
                        :
                              // do stuff
                     :
                     this.... ?
                               //do stuff
                              :
                                // ...

Upvotes: 0

Related Questions