When to Avoid && in React

Jun 30, 2023 · 3min

Preface

Here's the thing: in React, we often use && to achieve the effect of v-if in Vue, indicating whether a DOM element should be displayed under certain conditions.

For example, in Vue, you could write something like this. In this code, the div's v-if depends on the value of visible, which is usually a boolean. However, even if you set visible to 0, the div won't be displayed. So you could also use v-if to check list.length, indicating that when the list's length is 0, the related DOM element won't be displayed.

<template>
  <div v-if="visible"></div>
</template>

However, in React, we usually use && for conditional statements. If the condition is true, the DOM element following && is rendered. In this code, the display of the h1 tag depends on visible.

export default function App() {
  return (
    <div>
      {visible && <h1>Hello StackBlitz!</h1>}
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
}

However, using 0 to judge will result in an exception.

This easily causes problems when I write this kind of code because it displays 0 on the page.

{list.length && <h1>Hello StackBlitz!</h1>}

Reason

So why does it work in Vue? Let's see what form the code ultimately takes when using v-if in Vue. Following the previous example, the compilation result of Vue is as follows:

render(_ctx, _cache, $props, $setup, $data, $options) {
  return visible ? (_openBlock(), _createBlock("div", { key: 0 }))
    : _createCommentVNode("v-if", true)
}

Essentially, it's a ternary operator, so implicit type conversion occurs. When visible is true, the div is created; if false, a comment node (also called a placeholder node) is created in the current template, looking like this:

<!-- v-if -->

Although React uses JSX syntax, it's still fundamentally based on JavaScript. Therefore, during development, without Vue's template syntax, to understand why 0 && causes problems, we need to understand the essence of &&.

The Essence of &&

Since we're mentioning the essence of &&, this indicates that the problem isn't React's problem. Regarding && in MDN... The explanation above is:

Generally, when evaluating from left to right, this operator returns the value of the first false operand; if they are all true, it returns the value of the last operand.

Essentially, it evaluates the entire operation from left to right, returning immediately upon encountering the first false value, and returning the value of the last operand if all operands are true.

We also need to know that the following are converted to false:

false / null / NaN / 0 / ’’ / undefined

So here's the problem: although implicit type conversion occurs, the && operator preserves all non-Boolean values ​​and returns them as is:

"" && 1 // ''
0 && 1 // 0
NaN && 1 // NaN

Therefore, you know that when you use && in React (and not just React), it returns 0.

Similarly, NaN will also be displayed as NaN on the page. Be careful.

How to solve this?

So how do we solve this situation?

  1. Using !!

We can use !! to convert 0 to a boolean type.

!!list.length && <Component list={list} />
  1. Modifying the condition, not relying on implicit type conversion:

list.length >= 1 && <Component list={list} />
  1. Using a ternary expression to modify the return result:

list.length ? <Component list={list} /> : null
  1. Using a conditional statement:

if(list.length){return <Component list={list} />}
  1. Boolean type conversion:

Boolean(list.length) && <Component list={list} />

When using these methods, it's best to convert the content on the left side of the && operator to get the desired result, rather than encountering unpredictable problems.