DEV Community

Sam Atkinson
Sam Atkinson

Posted on

Nested Ternary statements in React JSX

After discovering our ESLinter hasn't been running for some time I've spent most of today going through trying to fix a whole bunch of eslint and a11y issues in our React app. I hit quite an interesting one:

/*eslint no-nested-ternary: "error"*/

Which basically means, don't do this:

const drink = dislikeCoke ? 'fanta' : likesCherry ? 'cherryCoke' : 'dietCoke';

Which I think in general everyone can get behind as a rule. It's not readable code, even when split over multiple lines with indentations, and should be broken out into if statements.

However, this is a very common pattern in React where we can use ternary statements to do conditional rendering in a component.

 <h1>Data Loader!</h1>
        { this.state.loading ? 
        <h2>It is Loading.</h2>
          : this.state.data ? 
          <h2>{this.state.data}</h2>
          :<h2>There was no result!</h2> 
        }

(This is a very contrived example).

I poked around on the internet for a while and the best alternative I've found to this is to extract the second part of the ternary into a stateless functional component. The component can still live in the same file so it's still quick and easy to comprehend, and I found it to be a nice way to encapsulate the UI code.

const DataDisplay = ({data}) => data ? 
          <h2>{data}</h2>
          :<h2>There was no result!</h2> 

          ...

          { this.state.loading ? 
        <h2>It is Loading.</h2>
          : <DataDisplay data={this.state.data}/>
        }

Full example codepen below:

Discussion (6)

Collapse
evadonnathan profile image
Nathan Dixon

Another option is to do an inline JSX functional component:

<h1>Data Loader!</h1>
        { () => {
            if (this.state.loading) { 
                return (<h2>It is Loading.</h2>)
            } else {
                if (this.state.data) { 
                    return (<h2>{this.state.data}</h2>)
                } else {
                    return <h2>There was no result!</h2> 
                }
            }
        }
Enter fullscreen mode Exit fullscreen mode
Collapse
josebrownex profile image
Jose Browne • Edited on

For others running into this issue the above won't work unless it's immedietly invoked

{(() => {
  ...
})()}
Enter fullscreen mode Exit fullscreen mode
Collapse
georgecoldham profile image
George

I just use indentation.

const drink = dislikeCoke
    ? 'fanta'
    : likesCherry
        ? 'cherryCoke'
        : 'dietCoke';
Collapse
aquasar profile image
Alex Quasar

I think your solutions is more complicated. I prefer the "Don't do this example"
Personally for me, Ternary in ternary is probably okay but if you are going to nest deeper than you probably should be rewriting your code in a nicer way, switch and case statements?

Collapse
peppermint_juli profile image
Juliana Jaime 🎃

It was very helpful, thank you!!

Collapse
gabrielmlinassi profile image
Gabriel Linassi

Cool! Much easier to get it on first glance. I just think when the code is not split into a different file, there's no need to pass the data as parameters since it has straight access to it.