113

I wanted to know if its possible to do nested if else if in ReactJS JSX?

I have tried various different ways and I am unable to get it to work.

I am looking for

if (x) {
  loading screen
} else {
  if (y) {
    possible title if we need it
  }
  main 
}

I have tried this but I can not get it to render. I have tried various ways. It always breaks once I add the nested if.

{
  this.state.loadingPage ? (
    <div>loading page</div>
  ) : (
    <div>
      this.otherCondition && <div>title</div>
      <div>body</div>
    </div>
  );
}

Update

I ended up choosing the solution to move this to renderContent and call the function. Both of the answers did work though. I think I may use the inline solution if it is for a simple render and renderContent for more complicated cases.

Thank you

8
  • 1
    just fyi if/else constructs aren't "loops" Commented May 19, 2016 at 0:34
  • The (<div>body</div>) part doesn't seem to belong to anything. That's an error. Otherwise what you have seems fine. Commented May 19, 2016 at 0:43
  • @FelixKling If I do it as <div>body<div> it will not work. The point is I want to have some data in the else that is always shown and another if for the title. Commented May 19, 2016 at 0:49
  • I understand, but foo ? bar : baz abc is not valid JavaScript. You want <div>{this.state.someBoolean ? ... : ...}<div>body</div></div> then. Commented May 19, 2016 at 0:52
  • You cannot have two expressions after each other: 4 5 is simply invalid. That's not a problem for statements. Commented May 19, 2016 at 0:59

6 Answers 6

201

You need to wrap your title and body in a container. That could be a div. If you use a fragment instead, you'll have one less element in the dom.

{ this.state.loadingPage
  ? <span className="sr-only">Loading... Registered Devices</span>
  : <>
      {this.state.someBoolean
        ? <div>some title</div>
        : null
      }
      <div>body</div>
    </>
}

I would advise against nesting ternary statements because it's hard to read. Sometimes it's more elegant to "return early" than to use a ternary. Also, you can use isBool && component if you only want the true part of the ternary.

renderContent() {
  if (this.state.loadingPage) {
    return <span className="sr-only">Loading... Registered Devices</span>;
  }

  return (
    <>
      {this.state.someBoolean && <div>some title</div>}
      <div>body</div>
    </>
  );
}

render() {
  return <div className="outer-wrapper">{ this.renderContent() }</div>;
}

Caveat to the syntax someBoolean && "stuff": if by mistake, someBoolean is set to 0 or NaN, that Number will be rendered to the DOM. So if the "boolean" might be a falsy Number, it's safer to use (someBoolean ? "stuff" : null).

Sign up to request clarification or add additional context in comments.

4 Comments

I ended up using your second solution with renderContent as I do believe it easier to read and use. Thank you
when using [] for rendering react throw warning of each child component should have a key prop.
You should use <></> (<React.Fragment>) instead of [].
Right. Updated.
60

Instead of nesting ternary operators as it is often suggested or creating a separate function that will not be reused anywhere else, you can simply call an inline expression:

<div className="some-container">
{
   (() => {
       if (conditionOne)
          return <span>One</span>
       if (conditionTwo)
          return <span>Two</span>
       else (conditionOne)
          return <span>Three</span>
   })()
}
</div>

3 Comments

"prettiest" solution in here but from a performance perspective, this will add some overhead since an IIFE is created every time a render gets invoked.
If you need a conditional rendering, it doesn't really matter wether it's IIFE or nested ternaries (which I grew to like since posting my original answer), or R.cond([...]). If anything, the "bigger" performance impact is the inline function creation. But in the big picture, it's a premature performance optimization and you'd be better off using PureComponent or ShouldComponentUpdate. My answer differs from the accepted answer mostly in the fact that you don't have to create a class member function that you won't use anywhere else and can just do it inline.
@dehumanizer your's solution worked for me. Thank you so much . More power to you :)
23

You can check multiple conditions to render components accordingly like below:

  this.state.route === 'projects'
  ? 
  <div> <Navigation onRouteChange={this.onRouteChange}/> Projects</div>
  :
  this.state.route === 'about'
  ?
  <div> <Navigation onRouteChange={this.onRouteChange}/> About</div>
  :
  this.state.route === 'contact'
  ?
  <div> <Navigation onRouteChange={this.onRouteChange}/> Contact</div>
  :
  <p> default </p>

1 Comment

This is so good. Exactly what I was looking for.
21

You can nest as many statements as possible. please follow this code assuming that this.state.firstTestValue, this.state.someTestValue and this.state.thirdValueTest are your test values from the state.

{this.state.firstTestValue
    ? <div >First Title</div>
    : [
        this.state.someTestValue
            ? <div>Second Title</div>
            : [
                this.state.thirdValueTest 
                ? <div>Some Third Title</div> 
                : <div>Last Title</div>
            ]
    ]
}

Comments

7

Your code in the alternative is not valid JavaScript/JSX expression:

(
  this.state.someBoolean ?
  (<div>some title</div>):(<div>some other title</div>)
  <div>body</div>
)

Lets simplify this to

(
  true ? 42 : 21
  3
)

This throws the error

Uncaught SyntaxError: Unexpected number(…)

You cannot just have two expression next to each other.

Instead you have to return a single value from the false branch of the conditional operator. You can do this by simply putting it in another JSX element:

(
  <div>
    {this.state.someBoolean ? (<div>some title</div>) : (<div>some other title</div>)}
    <div>body</div>
  </div>
)

If you want to only show "body" when "some other title" is shown, you need to move <div>body</div> into the false branch of the conditional operator:

(
  this.state.someBoolean ?
    (<div>some title</div>) :
    (<div>
       <div>some other title</div>
       <div>body</div>
    </div>)
)

Or maybe you want

(
  <div>
    {this.state.someBoolean ? (<div>some title</div>) : null}
    <div>body</body>
  </div>
)

9 Comments

The problem is that I only want body to show up in some other title. Using "body" might not have been the best choice. I can rewrite
Then your original code makes even less sense and doesn't mat your if...else example.What you want is this.state.someBoolean ? (<div>some title</div>):(<div><div>some other title</div><div>body</div></div>) then.
The thing is that I only want to show the title if another condition is true. The body will be shown as you have in the second example in the else section but then I need ANOTHER conditional on the title. The page shows either, A loading page OR a main page with or without a title
I updated my question with your example plus the additional conditional
Updated my answer. Note that all the examples only show the false branch of the outer conditional, because that's the only thing that was incorrect. If this is still not what you want, I really have no idea what you are talking about.
|
0

As the other answer suggest, there are various ways to do a nested if else in react. Which one to use depends on situation and preferences.

In my opinion, for best code readability, on this occassion it'd be best to move the content of else to separate function:

renderContent() {
     return (
         <div>
             { this.otherCondition && <div>title</div> }
             <div>body</div>
         </div>
     );
}

render() {
    return (
        <div>
            { ... }
            {
                this.state.loadingPage ?
                    <div>loading page</div>
                    :
                    this.renderContent()
            }
            { ... }
        </div>
    )
}

Or if it's simple enough (in case no other elements are rendered), I'd go with:

render() {
    if (this.state.loadingPage) {
        return (
            <div>loading page</div>
        )
    }
    return (
        <div>
            { this.otherCondition && <div>title</div> }
            <div>body</div>
        </div>
    );
}

Here's an article on conditional rendering in React, so please check it out if you're interested in more details on this topic.

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.