React rendering woes? Here’s how to solve unexpected ‘0’ renders

React rendering woes? Here’s how to solve unexpected ‘0’ renders

During my daily React-related pull request reviews, I often stumble across conditional renderings that are considered code smell. These conditions can cause problems, such as unexpectedly displaying values like a numeric 0 or the string ‘0’, because React only skips the rendering if something is a boolean or nullish (null or undefined):

return (
    <>
        // this will render nothing
        {null && <SomeFancyElement />} 

        // this will render nothing
        {undefined && <SomeFancyElement />} 

        // this will render nothing
        {false && <SomeFancyElement />} 
    </>
)

However, even though these values are skipped, they still exist as children and are included in the component’s children array. So it’s possible that the variable to the left of a short-circuit evaluation could return a 0 or ‘0’. Although these values are considered falsy in JavaScript, React will render them anyway:

return (
    <>
        // this will render <SomeFancyElement />
        {1 && <SomeFancyElement />} 
        
        // this will render <SomeFancyElement />
        {true && <SomeFancyElement />} 
        
        // this will render <SomeFancyElement />
        {'some string' && <SomeFancyElement />} 
        
        // and this will render '0'
        {0 && <SomeFancyElement />} 
    </>
)

So if the left side of a logical expression is truthy when evaluated, the right wide will render because the entire expression evaluates to true. So far, so fine. But on the other hand, if the left side is false, it short-circuit evaluates to a falsy expression, which then still renders this falsy expression accordingly. React will only skip rendering if the left side of type boolean, null, or undefined.

The quick fix way

Fortunately, there are a couple of ways to fix this little problem. The main goal is to make sure that the left side of a logical expression evaluates to type boolean, null, or undefined when it’s falsy. A quick but not perfect fix is to use a ternary operator instead of a short-circuited && evaluation in the conditional rendering block to solve the aforementioned problem and return a proper null instead of 0 or ‘0’:

return (
    <>
        {condition ? <SomeFancyElement /> : null}
    </>
)

The proper way

However, this only fixes the symptom, not the cause of the problem. Instead, the expression on the left should be converted to a boolean. This can be done by evaluating the expression using good old comparison operators (e.g. strict equal ===, strict not equal !==, greater/less than &rt;/< and greater/less than or equal &rt;=/<=), the boolean object (e.g., Boolean(expression)), or double negation (e.g., !!expression):

const expression = 0;

return (
    <>
        // fix by using comparison operators
        {expression > 0 && <SomeFancyElement />}

        // fix by using boolean object
        {Boolean(expression) && <SomeFancyElement />}

        // fix by using double-negation
        {!!expression && <SomeFancyElement />}
    </>
)

This way, unwanted values like 0 or ‘0’ won’t be rendered if the left-hand expression is falsy. Consider moving this check before the actual rendering block to keep the code simple and readable.

Hero image: Generated with DALL·E 3 on October 28, 2023 at 3:40 PM and edited with the Generative Fill tool in Adobe Photoshop.

Reply article Reply answer

By sending the reply, your message, your chosen name and the current time will be saved.
Nothing else. No IP address, no email address, no cookies.