Master Conditional Rendering in React: Handle Truthy/Falsy Values | Tips and Tricks

Master Conditional Rendering in React: Handle Truthy/Falsy Values | Tips and Tricks

·

7 min read

Introduction

React is a UI library that simplifies maintaining state and updating components. To render components the most common way is by making a list of components and then rendering it.

There are a lot of ways of rendering lists in React, the most common ones being map and filter methods that return arrays of components.

Conditional Rendering is a process of rendering a component if it meets a condition and rendering another component or nothing if it doesn't meet the condition. There are simple and complex ways of conditional rendering in React. We'll discuss the following ways:

  • Rendering with if else statement

  • Ternary Operator ? : in React

  • null to prevent component rendering

  • & and && operator

  • !! Double Negation and render using number values

Rendering with if...else statement

We create a Weather component that takes in props of isRaining and renders different returns different HTML based on the props.

import React from 'react';

function Weather(props) {
  const isRaining = props.isRaining;

  if (isRaining) {
    return (
      <div>
        <h1>It's raining!</h1>
        <p>Bring your raincoat.</p>
      </div>
    );
  } else {
    return (
      <div>
        <h1>It's a lovely day!</h1>
        <p>Enjoy the weather.</p>
      </div>
    );
  }
}

export default Weather;

While if else can work great in simple components like this but it is verbose and have low readability.

Drawback: We can't use if...else inside the JSX which can be a huge hurdle in DRY (don't repeat yourself) code.

Ternary Operator ? : in React

A ternary operator is a short form of an if...else statement with the added functionality of implicit return. Its syntax is:

condtion ? expression-if-true : expression-if-false

In JSX whole ternary operator is written in curly braces as { condition ? true : false } because curly braces are a way to write javascript in JSX. To return JSX in true / false expression use parenthesis ( ) to wrap JSX.

Let's take an example of the Employee component. In this example, the Employee component takes two props: name which is the name of the employee to display, and isEmployed, which is a boolean value indicating whether the employee is currently employed or not. The component uses a ternary operator in the return statement to conditionally render different content based on the value of isEmployed. If isEmployed is true, the component will render a paragraph that says "Currently employed". If isActive is false, the component will render a paragraph that says "Not currently employed".

props object looks like this

props = {
    isEmployed: true;
    name: "Elijah Williams"
}
import React from 'react';

function Employee(props) {
  const isEmployed = props.isEmployed;

  return (
    <div>
      <h2>{props.name}</h2>
      {isEmployed ? (
        <p>Currently employed</p>
      ) : (
        <p>Not currently employed</p>
      )}
    </div>
  );
}

export default Employee;

Use null to prevent component rendering

Not all the time do we need to render a component in a false case. So, we may use <div> </div> because we can't leave expression space empty, it must be filled with an expression.

props object looks like this

props = {
    name: "LeBron James",
    team: "Los Angeles Lakers",
    jerseyNumber: 6,
    isPlaying: true
}
import React from 'react';

function NBAPlayer(props) {
  const {name, team, jerseyNumber, isPlaying } = props;

  return (
    <div>
      <h2>{name}</h2>
      { isPlaying ? (
        <div>
          <p>Currently playing for {team}</p>
          <p>Jersey number: {jerseyNumber}</p>
        </div>
      ) : (
          // we want to render nothing
          <div></div>
      ) }
    </div>
  );
}

export default NBAPlayer;

The problem, in this case, is that it'll render an extra div which will always rerender when the NBAPlayer component is rerendered.

To solve this problem we just use null because React doesn't render null in the UI. The NBAPlayer component will look like this:

import React from 'react';

function NBAPlayer(props) {
  const isPlaying = props.isPlaying;

  return (
    <div>
      <h2>{props.name}</h2>
      { isPlaying ? (
        <div>
          <p>Currently playing for {props.team}</p>
          <p>Jersey number: {props.jerseyNumber}</p>
        </div>
      ) : null }
    </div>
  );
}

export default NBAPlayer;

If isPlaying is true, the component will render a div with two paragraphs containing information about the player's team and jersey number. If isPlaying is false, the component will render null, which will cause nothing to be rendered to the DOM.

& and && operator

& operator performs a bitwise AND operation on two values, treating them as binary numbers. For example, 2 & 9 would evaluate to 1, because in binary, 2 is 0010 and 9 is 1001, and the result of a bitwise AND operation on those values return 1 in decimal value.

&& operator is a logical AND operator.

  • It evaluates two expressions and returns the value of the second expression if the first expression is truthy,

  • OR it returns the value of the first expression if it is falsy.

For example, true && 5 would evaluate to 5, because true is truthy, so the expression evaluates to the second operand, which is 5. However, false && 5 would evaluate to false, because false is falsy, so the expression evaluates to the first operand, which is false.

Example of a patient: this component renders the sick status conditionally.

import React from "react";

function Patient(props) {
  const { name, age, isSick } = props;

  return (
    <div>
      <h2>Patient Information</h2>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
      {isSick && <p>Status: Sick</p>}
    </div>
  );
}

export default Patient;

The expression {isSick && <p>Status: Sick</p>} evaluates to true if isSick is truthy and false otherwise. If it evaluates to true, it renders the <p>Status: Sick</p> element. If it evaluates to false, it doesn't render anything at all (since false is a falsy value in JavaScript and React will ignore it).

This is a less verbose and concise way to conditionally render as well as not render anything in case of falsy value, unlike using an empty <div/> which causes recurring rerenders and negatively impacts performance.

Use !! to render using numbers

!! converts truthy/falsy values to boolean literals true OR false respectively. First ! converts truthy value to false by negating it, then second ! converts the false value back to true. By this logic, we have converted truthy value to true.

If we use the length or index of an array or any other number to compose our condition for rendering, then it poses a risk of becoming a 0, which is a falsy value. And if we recall && operator, in case the first value is a falsy value React will use 0 instead of false.

Reason: React skips rendering anything that is boolean or undefined and will render anything that is string or number.

We use quotes.length in the following example where we render all the quotes present in our quotes state.

import { useState } from 'react'
import {quotesList} from './quotes'

function App() {
  const [quotes, setQuotes] = useState(["If life were predictable it would cease to be life"]);

    const addMessage = () => {
        if(quotesList.length > quotes.length){
          setQuotes([...quotes, quotes[quotes.length]])
        }
      }

    const removeQuote = () => {
        setQuotes(quotes.slice(0, quotes.length - 1))
    }


  return (
    <div className="App">
      <h1>Conditional Rendering</h1>
      {
        quotes.length &&
        quotes.map((quote) => (
          <h3 className='quote'>{quote}</h3>
        ))
      }
      <button onClick={addQuote}>Add Quote</button>
      <button onClick={removeQuote}>Clear Quote</button>
    </div>
  )
}

export default App

We have two buttons to add and remove Quote which are attached to two functions addQuote() and removeQuote(). We use && with quotes.length to map a h3 with a quote inside it. When Add Quote button is clicked a new quote is added to quotes state. On the other hand, when Clear Quote button is clicked a single quote is removed from quotes state using slice() method.

In the above case, if all the quotes are cleared from the state, 0 will be rendered instead of <h3 className='quote'>{quote}</h3> as 0 is not ignored.

But if we use double not !! before quotes.length it'll return false instead of 0 when the length of quotes is 0. If we recall && operator, when the first expression is false, false is returned and the second expression is not considered. As false will be ignored by React 0 will not be rendered in the UI when the length of quotes becomes 0.

{
    !!quotes.length &&
         quotes.map((quote) => (
              <h3 className='quote'>{quote}</h3>
        ))
}

Conclusion

If else is the most basic way of conditional rendering in React.

The ternary operator can be used for conciseness.

Null is used to prevent rendering components when the condition is false.

&& used to render conditionally without if ... else or ternary operator. There is no need for null either.

!! used when a number is used with && operator. It converts truthy/falsy to true and false.

Recommendation

While choosing which method to use for conditional rendering depends on the complexity of the app and specific use case. However, Ternary operator coupled with null and use of && operator can be versatile in medium-level applications.