Use ternaries rather than logical AND in JSX. Or not?

October 24, 2021

Can you guess what can be problematic with the following code example?

index.jsx
1const SomeComponent = ({ someArrayProp }) => {
2 return (
3 someArrayProp.length &&
4 someArrayProp.map((item) => {
5 return <div>{item}</div>
6 })
7 )
8}

Take a closer look at line 3. Can you see it now? We are checking if someArrayProp has length. What will happen if someArrayProp is an empty array []? You will render an 0.

The logical AND (&&) operator converts the first expression (someArrayProp.length) into the boolean. If the evaluated expression is true, it returns the second expression; else, it returns the first expression (in our case, 0).

Ternary operator

What can be a solution to this issue? Using a ternary operator to be more explicit what you want to render in the falsy scenario:

index.jsx
1const SomeComponent = ({ someArrayProp }) => {
2 return someArrayProp.length
3 ? someArrayProp.map((item) => {
4 return <div>{item}</div>
5 })
6 : null
7}

Optional chaining

But I can see another problem, can you see it as well? What will happen if someArrayProp won't be passed into the SomeComponent component? You will get this error message: Cannot read properties of undefined (reading 'length') (Your error message may differ)

We can simply fix this with the optional chaining operator:

index.jsx
1const SomeComponent = ({ someArrayProp }) => {
2 return someArrayProp?.length
3 ? someArrayProp.map((item) => {
4 return <div>{item}</div>
5 })
6 : null
7}

You may think that you can remove someArrayProp?.length and use optional chaining before calling the map method:

index.jsx
1const SomeComponent = ({ someArrayProp }) => {
2 return someArrayProp?.map((item) => {
3 return <div>{item}</div>
4 })
5}

But you will encounter a different error: SomeComponent(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

As the error message suggests, we need to either render something or if we do not want to render the component, we need to return a null.

Nullish coalescing operator

Is there any other approach we can try here? Of course, we can leverage a nullish coalescing operator!

index.jsx
1const SomeComponent = ({ someArrayProp }) => {
2 return (
3 someArrayProp?.map((item) => {
4 return <div>{item}</div>
5 }) ?? null
6 )
7}

Keep in mind that it works only because optional chaining returned undefined, so optional chaining returns a second expression (in our case, null).

Usage of logical AND within if statements

We are used to using a logical AND operator in the if condition, e.g., if both of these values are truthy, proceed further, otherwise don't. But we need to keep in mind that if both of our expressions aren't truthy, the falsy value is returned.

index.js
10 && true // 0 (The first expression is falsy and it is returned)
2true && 0 // 0 (The first expression is truthy, the second expression is returned)
3
4false && true // false (The first expression is falsy and it is returned)
5true && false // false (The first expression is truthy, the second expression is returned)

Branching syntax

Using branching syntax (ternary operator, if statement) may be better. It is more explicit about what we want to achieve, but also it can be more verbose. Here is example how the same code would look like using if statement:

index.jsx
1const SomeComponent = ({ someArrayProp }) => {
2 let children = null
3
4 if (someArrayProp?.length) {
5 children = someArrayProp.map((item) => {
6 return <div>{item}</div>
7 })
8 }
9
10 return children
11}

From my perspective, ternary is more readable than using the if statement (Keep in mind that readability is subjective, and it is connected with familiarity more than you would expect.).

Conclusion

Personally, I would go with a nullish coalescing operator for our use case, as I like how concise it is. But you need to understand it properly to leverage it. Here you can read more about nullish coalescing.

I'm aware that we could solve this problem by using different approaches. Still, this article aims to elaborate more on how I would approach this and the pros and cons of the specified approach.

Share this post on Twitter