DEV Community

Ben Read
Ben Read

Posted on

Should I use ternary or the logical and operator?

Templating with JSX in React is easy ... until it's not. Recently a colleague recommended I use the logical and operator instead of a ternary. However once we'd dug into it a little, we found these operators do very different things ...

Quite often we follow this pattern for brevity, and there's good value doing it if there's only one variable at play:

{
  isLoggedIn && <SomeComponent />;
}
Enter fullscreen mode Exit fullscreen mode

This avoids us from having to write something like

{
  isLoggedIn ? <SomeComponent /> : null;
}
Enter fullscreen mode Exit fullscreen mode

which is totally redundant here, since if it's value is false, it won't return the component.

However, when there's a couple of things going on you might find it doing something unexpected:

{
  formErrors.likesPotatoes ||
  formErrors.likesBananas ||
  formErrors.likesCake ? (
    <NotificationMessage icon="alert" status="error">
      <p>
        Please ensure that all the required questions have been answered before
        proceeding.
      </p>
    </NotificationMessage>
  ) : null;
}
Enter fullscreen mode Exit fullscreen mode

is not equivalent to:

{
  formErrors.likesPotatoes ||
    formErrors.likesBananas ||
    (formErrors.likesCake && (
      <NotificationMessage icon="alert" status="error">
        <p>
          Please ensure that all the required questions have been answered
          before proceeding.
        </p>
      </NotificationMessage>
    ));
}
Enter fullscreen mode Exit fullscreen mode

With the ternary operator (isTrue ? dothis : dothat), our <NotificationMessage/> will show when any of the conditions are met. The logical AND (isTrue && dothat) will only show the component if all of the conditions are met.

Why?

The Difference between the logical AND and ternaries

Ternaries work similar to the if operator. So it short circuits (closes off before any other variable is assessed), and returns true if any of the values are true.

On the other hand, the logical AND operator returns true only if and only if all of its operands are true.

In our case, when checking for form errors, we want to show a notification if any of the fields have an error. So the ternary is the way to go.

Alternative 1: abstract it

There is another way of handling this situation where you could use the logical AND: chain those errors in a variable before returning the JSX:

const hasError =
  formErrors.likesPotatoes || formErrors.likesBananas || formErrors.likesCake;
return (
  <>
    {hasError && (
      <NotificationMessage icon="alert" status="error">
        <p>
          Please ensure that all the required questions have been answered
          before proceeding.
        </p>
      </NotificationMessage>
    )}
  </>
);
Enter fullscreen mode Exit fullscreen mode

Alternative 2: Wrap it

My friend Warrick Hill mentioned that you could also wrap the options in brackets to ensure they get evaluated together and therefore don't short circuit. This is how mathematical bracket operators work, where everything inside the brackets gets evaluated first, for example (2 * 3) + 2 = 8 but 2 \* (3 + 2) = 10:

return (
  <>
    {(formErrors.likesPotatoes ||
      formErrors.likesBananas ||
      formErrors.likesCake) && (
      <NotificationMessage icon="alert" status="error">
        <p>
          Please ensure that all the required questions have been answered
          before proceeding.
        </p>
      </NotificationMessage>
    )}
  </>
);
Enter fullscreen mode Exit fullscreen mode

Although Warrick points out that this is harder to spot than the alternative #1 above.

Thanks

Thanks to @niyogakiza and @crgeary (as well as Warrick) for their help with this article.

This post was originally published on my personal site: https://deliciousreverie.co.uk/post/should-i-use-ternary-or-logicaland-in-react/

Top comments (2)

Collapse
 
moopet profile image
Ben Sinclair

I'm a fan of making things as easy to read as possible.

In anything shy of a line in the shell I'm going to choose ternary over logical operators because it's easier for me to read, and my naive assumption is that it'll be the same for other people.

In the examples you've given, where you make the lines longer and more verbose, and you add further conditions to show how they get more difficult to read... I'd use an if block, and perhaps assign a variable with a clear name. You did this with hasError where it makes perfect sense to build a flag from a bunch of other flags. Not only does that make it easier to scan with your eyes, but it partially documents the code. You can immediately see that the component is shown if there's any error, because it's called hasError and that's defined above.

Collapse
 
lexlohr profile image
Alex Lohr

The issue here is the brackets, because || will yield the first truthy expression, as shown in this simplified example:

true || (true && 'yes') // true
(true || true) && 'yes' // 'yes'
Enter fullscreen mode Exit fullscreen mode