JavaScript do expression: if statement without else
Asked Answered
P

5

9

I have a question about the proposed JavaScript do expression construct. There are many examples that show how it can be used to return a value from a conditional statement that has both if and else. Also valid for if with else if and else.

What about a conditional that has just an if clause but no else if or else? Is this valid usage of the do expression?

My use case is for conditionally displaying content in a React component. I would like to write JSX code like so, but I am not sure if it is valid:

export default function myComponent(props) {
  return (
    <div>
      {do {
        if (true) {
          <p>If statement is true</p>
        }
      }}
      <p>I am always rendered</p>
    </div>
  );
}

I also asked the question in this gist.

Pocketful answered 14/8, 2017 at 4:10 Comment(1)
do expression is a stage 1 proposal, not part of ES2016 (ES7).Tried
M
3

Here is what Babel does:

Input:

<p>
  {do {
    if (true) {
      <a/>
    }
  }}
</p>

Output:

React.createElement(
  "p",
  null,
  true ? React.createElement("a", null) : void 0
);

This makes sense to me. The return value in the implied else would be undefined.

Mosstrooper answered 14/8, 2017 at 4:30 Comment(4)
In React, you want the return value for else (in this case) to be null, not undefined. Better to explicitly return null as in this answerBushed
Then open a ticket with Babel. I didn't write this code in my answer, I'm only showing what the compiler did.Mosstrooper
I was talking about the original source code before Babel transpiles it. So {do { if (true) { <a/> } null }}Bushed
...or it looks like in the current version of the spec you would have an explicit else block (else { null }); not sure if Babel supports that yetBushed
G
18

Not sure about do, also as mentioned by @Felix Kling

do expression is a stage 1 proposal, not part of ES2016 (ES7).


You can write it like this using ternary operator, and return null if condition fails:

export default function myComponent(props) {
    return (
        <div>
            {
                true?
                    <p>If statement is true</p>
                :null
            }
            <p>I am always rendered</p>
        </div>
    );
}

Or Use && Operator:

export default function myComponent(props) {
    return (
        <div>
            {
                true && <p>If statement is true</p>
            }
            <p>I am always rendered</p>
        </div>
    );
}

Check the DOC for more details about Conditional Rendering.

Gare answered 14/8, 2017 at 4:15 Comment(1)
&& operator is exactly what I was looking for. It makes the code cleaner and more succinct.Cattalo
T
6

Why not simply do this ? Using the Ternary operator

export default function myComponent(props) {
  return (
    <div>
      { true ? <p>If statement is true</p> : null }
      <p>I am always rendered</p>
    </div>
  );
}
Torp answered 14/8, 2017 at 4:15 Comment(0)
M
3

Here is what Babel does:

Input:

<p>
  {do {
    if (true) {
      <a/>
    }
  }}
</p>

Output:

React.createElement(
  "p",
  null,
  true ? React.createElement("a", null) : void 0
);

This makes sense to me. The return value in the implied else would be undefined.

Mosstrooper answered 14/8, 2017 at 4:30 Comment(4)
In React, you want the return value for else (in this case) to be null, not undefined. Better to explicitly return null as in this answerBushed
Then open a ticket with Babel. I didn't write this code in my answer, I'm only showing what the compiler did.Mosstrooper
I was talking about the original source code before Babel transpiles it. So {do { if (true) { <a/> } null }}Bushed
...or it looks like in the current version of the spec you would have an explicit else block (else { null }); not sure if Babel supports that yetBushed
C
2

Yes, it is a valid syntax to write a do expression without an else and it will return an undefined (void 0).

let a = do {
  if (false) true
}

// a === undefined

We can also return a value at the end without even using else like this:

let a = do {
  if (false) true
  null
}

// a === null

Especially for ReactJS, we have to return a null even using the do expression, because if it doesn't return something, the return value will be undefined which of course will error break the component rendering:

export default function myComponent(props) {
  return (
    <div>
      {do {
        if ([condition]) {
          <p>If statement is true</p>
        }
        null
      }}
      <p>I am always rendered</p>
    </div>
  );
}

Or, use the Nullish coalescing operator ?? which will also catch undefined:

export default function myComponent(props) {
  return (
    <div>
      {do {
        if ([condition]) {
          <p>If statement is true</p>
        }
      } ?? null}
      <p>I am always rendered</p>
    </div>
  );
}

Other answers here suggest why bother using do expression since we can do this using the Conditional (ternary) operator ?:, and the answer is that using the ternary operator when we'll have more than one condition won't be syntactical friendly and it will lead in miss-renders and hard time understanding the logic for developers:

export default function myComponent(props) {
  return (
    <div>
      {[condition1]
        ? <p>If condition1 is true</p> :
       [condition2]
        ? <p>If condition2 is true</p> :
       [condition2]
        ? <p>If condition3 is true</p> :
       [condition4]
        ? <p>If condition4 is true</p> :
        null
      }
      <p>I am always rendered</p>
    </div>
  );
}

and that's one of the reasons behind the proposal and existence of the do expression; it will make multiple conditional expressions syntactical friendly:

export default function myComponent(props) {
  return (
    <div>
      {do {
        if ([condition1]) <p>If condition1 is true</p>
        if ([condition2]) <p>If condition2 is true</p>
        if ([condition3]) <p>If condition3 is true</p>
        if ([condition4]) <p>If condition4 is true</p>
      } ?? null}
      <p>I am always rendered</p>
    </div>
  );
}
Chace answered 28/6, 2021 at 20:49 Comment(1)
It looks like this is no longer true in the latest version of the do expressions proposal, and explicitly writing else is more readable anyway. But this answer is a great explanation of why you'd want to use a do expression.Bushed
C
2

You can do it simply, using conditioanl rendering:

    {condition && jsx-element}

Example:

    {relationshipStatus===RelationshipStatus.SINGLE && <ShowIAmSingleComponent />}

Whenever this relationshipStatus takes value of RelationshipStatus.SINGLE, it will render this ShowIAmSingleComponent component.

Simple as react.

Canicula answered 13/12, 2021 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.