How to do a nested if else statement in ReactJS JSX?

112,191

Solution 1

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).

Solution 2

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>

Solution 3

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>
            ]
    ]
}

Solution 4

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>

Solution 5

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>
)
Share:
112,191

Related videos on Youtube

ALM
Author by

ALM

Updated on January 30, 2022

Comments

  • ALM
    ALM over 2 years

    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

    • Pointy
      Pointy almost 8 years
      just fyi if/else constructs aren't "loops"
    • Felix Kling
      Felix Kling almost 8 years
      The (<div>body</div>) part doesn't seem to belong to anything. That's an error. Otherwise what you have seems fine.
    • ALM
      ALM almost 8 years
      @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.
    • Felix Kling
      Felix Kling almost 8 years
      I understand, but foo ? bar : baz abc is not valid JavaScript. You want <div>{this.state.someBoolean ? ... : ...}<div>body</div></div> then.
    • Felix Kling
      Felix Kling almost 8 years
      You cannot have two expressions after each other: 4 5 is simply invalid. That's not a problem for statements.
    • Felix Kling
      Felix Kling almost 8 years
      Maybe that's your confusion: foo ? bar : baz abc is interpreted as (foo ? bar : baz) (abc) not as foo ? bar : (baz abc). But both are invalid anyway.
    • Felix Kling
      Felix Kling almost 8 years
      Re "Updated as solution below but this will still not render." I missed {...} in my code, you can see the updated version in my code. Also please don't don't change your original question, because my answer doesn't make sense now anymore (I rolled back your edit).
    • ALM
      ALM almost 8 years
      The original code is not the issue, the problem is I still do not see how to nest another condition within the initial if (X) ? a : b ( nested if (y) (title) main)
  • ALM
    ALM almost 8 years
    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
  • Felix Kling
    Felix Kling almost 8 years
    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.
  • ALM
    ALM almost 8 years
    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
  • ALM
    ALM almost 8 years
    I updated my question with your example plus the additional conditional
  • Felix Kling
    Felix Kling almost 8 years
    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.
  • ALM
    ALM almost 8 years
  • ALM
    ALM almost 8 years
    I updated the question to include what I originally asked about how to put a nested conditional inside another conditional. I would like to display a loading page or main page but in the main page it needs a condition on if it has a title, hence the nested conditional. I updated your solution with the additional condition .
  • Felix Kling
    Felix Kling almost 8 years
    So you already have the outer conditional, {a ? b : c}. You simply take my last example and replace c with it. As I said, only the false branch of the outer conditional is incorrect. Your outer conditional is fine and hence I haven't repeated it. Or in more concrete terms: Replace the line this.otherCondition && <div>title</div> in your updated example with {this.state.someBoolean ? (<div>some title</div>) : null} from my example.
  • ALM
    ALM almost 8 years
    Thank you for your help. In the end it turns out I had something else causing the runtime error. I made the changes you selected and it works.
  • ALM
    ALM almost 8 years
    I ended up using your second solution with renderContent as I do believe it easier to read and use. Thank you
  • dipole_moment
    dipole_moment over 5 years
    "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.
  • dehumanizer
    dehumanizer over 5 years
    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.
  • andromeda
    andromeda over 2 years
    This is so good. Exactly what I was looking for.
  • sashiksu
    sashiksu over 2 years
    when using [] for rendering react throw warning of each child component should have a key prop.
  • GonEbal
    GonEbal over 2 years
    You should use <></> (<React.Fragment>) instead of [].
  • Neal Ehardt
    Neal Ehardt over 2 years
    Right. Updated.