Esteban Herrera Family man. Java and JavaScript developer. Swift and VR/AR hobbyist. Like books, movies, and still trying many things. Find me at eherrera.net

React conditional rendering: 9 methods with examples

14 min read 4183

React Conditional Rendering

Editor’s note: This tutorial was last updated on 16 June 2022 to reflect changes made in React v18.

JSX is a powerful extension to JavaScript that allows us to define UI components. It doesn’t support loops or conditional expressions directly, however, the addition of conditional expressions has been discussed before.

If you want to iterate over a list to render more than one component or implement some conditional logic, you have to use pure JavaScript. You don’t have a lot of options with looping, either. Most of the time, map will cover your needs. But conditional rendering is another story.

What is conditional rendering in React?

In React, conditional rendering refers to the process of delivering elements and components based on certain conditions.

There’s more than one way to use conditional rendering in React. Like with most things in programming, some things are better suited than others depending on the problem you’re trying to solve.

In this tutorial, we’ll cover the most popular ways to implement conditional rendering in React, also reviewing some tips and best practices.

To demonstrate how all these methods work, we’ll implement a component with view and edit functionality, as seen in the gif below:

Component View Edit Functionality

You can fork all the examples in JSFiddle to follow along. We’ll start with the most naive implementation, using an if...else block and build it from there.

How to write if...else in React

Create a component with the following state:

import React from "react"

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "",
      inputText: "",
      mode: "view",
    };
  }
}

You’ll use one property for the saved text and another for the text that is being edited. A third property will indicate if you are in edit or view mode.

Next, add some methods for handling input text, then save and edit events as follows:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {text: '', inputText: '', mode:'view'};

    this.handleChange = this.handleChange.bind(this);
    this.handleSave = this.handleSave.bind(this);
    this.handleEdit = this.handleEdit.bind(this);
  }

  handleChange(e) {
    this.setState({ inputText: e.target.value });
  }

  handleSave() {
    this.setState({text: this.state.inputText, mode: 'view'});
  }

  handleEdit() {
    this.setState({mode: 'edit'});
  }
}

Now, for the render method, check the mode state property to either render an edit button or a text input and a save button, in addition to the saved text:

class App extends React.Component {
  // …
  render () {
    if(this.state.mode === 'view') {
      return (
        <div>
          <p>Text: {this.state.text}</p>
          <button onClick={this.handleEdit}>
            Edit
          </button>
        </div>
      );
    } else {
      return (
        <div>
          <p>Text: {this.state.text}</p>
            <input
              onChange={this.handleChange}
              value={this.state.inputText}
            />
          <button onClick={this.handleSave}>
            Save
          </button>
        </div>
      );
    }
}

Here’s the complete Fiddle to try it out:

An if...else block is the easiest way to solve the problem, but I’m sure you know this is not a good implementation. While it works well for simple use cases and every programmer knows how it works, there’s a lot of repetition, and the render method looks crowded.

Let’s simplify it by extracting all the conditional logic to two render methods: one to render the input box and another to render the button:

class App extends React.Component {
  // …

  renderInputField() {
    if(this.state.mode === 'view') {
      return <div></div>;
    } else {
      return (
          <p>
            <input
              onChange={this.handleChange}
              value={this.state.inputText}
            />
          </p>
      );
    }
  }

  renderButton() {
    if(this.state.mode === 'view') {
      return (
          <button onClick={this.handleEdit}>
            Edit
          </button>
      );
    } else {
      return (
          <button onClick={this.handleSave}>
            Save
          </button>
      );
    }
  }

  render () {
    return (
      <div>
        <p>Text: {this.state.text}</p>
        {this.renderInputField()}
        {this.renderButton()}
      </div>
    );
  }
}

Here’s the complete Fiddle to try it out:

Let’s imagine that we have more than two branches that depend on the same variable to evaluate the condition. You might consider using a large if...else block, like in the code below:

if(this.state.mode === 'a') {
  // ...   
} else if(this.state.mode === 'b') {
  // ...
} else if(this.state.mode === 'c') {
  // ...
} else {
  // ...
}

Instead, you can use a switch statement as follows:

switch(this.state.mode) {
  case 'a':
    // ...
  case 'b':
    // ...
  case 'c':
    // ...
  default:
    // equivalent to the last else clause ...
}

The switch statement may add a bit more clarity, but it’s still too verbose, and it doesn’t work with multiple or different conditions. Just like an if...else statement, you can’t use a switch statement inside of a return statement with JSX unless you use immediately invoked functions, which we’ll cover later.

Let’s look at some additional techniques to improve this code. Notice that the method renderInputField returns an empty <div> element when the app is in view mode. However, this is not necessary.

Prevent rendering with null

If you want to hide a component, you can make its render method return null, so there’s no need to render an empty, different element as a placeholder. One important thing to keep in mind when returning null, however, is that even though the component doesn’t show up, its lifecycle methods are still fired.



Take, for example, the following Fiddle, which implements a counter with two components:

The Number component only renders the counter for even values. Otherwise, it returns null. When you look at the console, however, you’ll see that componentDidUpdate is always called regardless of the value returned by render.

Number Component Render Even Value

In our example, change the renderInputField method to look like the following code:

  renderInputField() {
    if(this.state.mode === 'view') {
      return null;
    } else {
      return (
          <p>
            <input
              onChange={this.handleChange}
              value={this.state.inputText}
            />
          </p>
      );
    }
  }

The complete Fiddle is below:

One advantage of returning null instead of an empty element is that you’ll improve the performance of your app a little bit because React won’t have to unmount the component to replace it.

For example, if you open the Inspector tab from the Fiddle that renders the empty <div> element, you’ll see how the <div> element under the root is always updated:

React Inspector Div Updated

This differs from when null is returned to hide the component and the <div> element is not updated when the edit button is clicked:

Null Returned Hide Component

You can check out the docs to learn more about reconciliation in React, which basically refers to how React updates the DOM elements and how the diffing algorithm works.

Although in this simple example, the performance improvement is insignificant, when you are working with big components, the difference is more noticeable. Later, we’ll cover more of the performance implications of conditional rendering. For now, let’s continue to improve our example.

React element variables

Because I don’t like having more than one return statement in methods, I’ll use a variable to store the JSX elements and only initialize it when the condition is true:

renderInputField() {
    let input;

    if(this.state.mode !== 'view') {
      input = 
        <p>
          <input
            onChange={this.handleChange}
            value={this.state.inputText} />
        </p>;
    }

      return input;
  }

  renderButton() {
    let button;

    if(this.state.mode === 'view') {
      button =
          <button onClick={this.handleEdit}>
            Edit
          </button>;
    } else {
      button =
          <button onClick={this.handleSave}>
            Save
          </button>;
    }

    return button;
  }

The code above gives the same result as returning null from those methods. Here’s the Fiddle to try it out:

Although the main render method is more readable this way, it isn’t necessary to use if...else blocks or something like a switch statement and secondary render methods. Let’s try a simpler approach.


More great articles from LogRocket:


The ternary operator in React

Instead of using an if...else block, we can use the ternary conditional operator:

condition ? expr_if_true : expr_if_false

The operator is wrapped in curly braces, and the expressions can contain JSX, which you can wrap in parentheses to improve readability. The operator can also be applied in different parts of the component.

Let’s apply it to the example to see this in action. I’ll remove renderInputField and renderButton, and in the render method, I’ll add a variable to know if the component is in view or edit mode:

render () {
  const view = this.state.mode === 'view';

  return (
      <div>
      </div>
  );
}

Now, you can use the ternary operator to return null if the view mode is set, or set the input field otherwise:

  // ...

  return (
      <div>
        <p>Text: {this.state.text}</p>

        {
          view
          ? null
          : (
            <p>
              <input
                onChange={this.handleChange}
                value={this.state.inputText} />
            </p>
          )
        }

      </div>
  );

Using a ternary operator, you can declare one component to render either a save or an edit button by changing its handler and label correspondingly:

  // ...

  return (
      <div>
        <p>Text: {this.state.text}</p>

        {
          ...
        }

        <button
          onClick={
            view 
              ? this.handleEdit 
              : this.handleSave
          } >
              {view ? 'Edit' : 'Save'}
        </button>

      </div>
  );

Here’s the Fiddle to try it out:

As mentioned before, this operator can be applied in different parts of the component, even inside return statements and JSX, acting as a one-line if...else statement. However, for this exact reason, things can get messy pretty quickly.

Let’s review another technique that can help improve the code.

Short-circuit AND operator &&

There is a special case where the ternary operator can be simplified. When you want to render either something or nothing, you can only use the && operator. Unlike the & operator, && doesn’t evaluate the right-hand expression if only the left-hand expression can decide the final result.

For example, if the first expression evaluates to false, false && …, it’s not necessary to evaluate the next expression because the result will always be false.

In React, you can have expressions like the following:

return (
    <div>
        { showHeader && <Header /> }
    </div>
);

If showHeader evaluates to true, then the <Header/> component will be returned by the expression. If showHeader evaluates to false, the <Header/> component will be ignored, and an empty <div> will be returned.

Consider the following expression:

{
  view
  ? null
  : (
    <p>
      <input
        onChange={this.handleChange}
        value={this.state.inputText} />
    </p>
  )
}

The code above can be turned into the following code snippet, as seen in the Fiddle below:

!view && (
  <p>
    <input
      onChange={this.handleChange}
      value={this.state.inputText} />
  </p>
)

Here’s the complete Fiddle:

Although the code looks better in this example, that isn’t always the case. For example, consider a complex, nested set of the following conditions:

return (
  <div>
    { condition1
      ? <Component1 />
      : ( condition2
        ? <Component2 />
        : ( condition3
          ? <Component3 />
          : <Component 4 />
        )
      )
    }
  </div>
);

This can become a mess pretty quickly. For that reason, sometimes you might want to use other techniques, like immediately invoked functions.

Immediately invoked function expressions (IIFEs)

As the name implies, immediately invoked function expressions (IIFEs) are functions that are executed immediately after they are defined, so there is no need to call them explicitly.

Generally, you’d define and execute a function at a later point, like in the following code snippet:

function myFunction() {

// ...

}

myFunction();

But, if you want to execute the function immediately after it is defined, you have to wrap the whole declaration in parentheses to convert it to an expression. You’d execute it by adding two more parentheses and pass any arguments that the function may take:

( function myFunction(/* arguments */) {
    // ...
}(/* arguments */) );

Adding extra parentheses:

( function myFunction(/* arguments */) {
    // ...
} ) (/* arguments */);

Since the function won’t be called in any other place, you can drop the name:

( function (/* arguments */) {
    // ...
} ) (/* arguments */);

Or, you can use arrow functions:

( (/* arguments */) => {
    // ...
} ) (/* arguments */);

In React, you use curly braces to wrap an IIFE, put all the logic you want inside it, like an if...else, switch, ternary operators, etc., and return whatever you want to render.

In other words, inside an IIFE, we can use any type of conditional logic. This allows us to use if...else and switch statements inside return statements, as well as JSX if you consider it to improve the readability of the code:

return (
  <div>
    <p>...</p>
    {
      (()=> {
        switch (condition) {
          case 1: return <Component1 />;
          case 2: return <Component2 />;
          default: null;
        }
      })()
     }
  </div>
);

For example, the logic to render the save or edit button could look like the following with an IIFE:

{
  (() => {
    const handler = view 
                ? this.handleEdit 
                : this.handleSave;
    const label = view ? 'Edit' : 'Save';

    return (
      <button onClick={handler}>
        {label}
      </button>
    );
  })()
}

Here’s the complete Fiddle:

React subcomponents

Sometimes, an IFFE might seem like a hacky solution. After all, we’re using React. The recommended approach is to split up the logic of your app into as many components as possible and to use functional programming instead of imperative programming.

Moving the conditional rendering logic to a subcomponent that renders different things based on its props would be a good option. But, in this example, I’m going to do something a bit different to show you how you can go from an imperative solution to more declarative and functional solution.

I’ll start by creating a SaveComponent:

const SaveComponent = (props) => {
  return (
    <div>
      <p>
        <input
          onChange={props.handleChange}
          value={props.text}
        />
      </p>
      <button onClick={props.handleSave}>
        Save
      </button>
    </div>
  );
};

As properties, it receives everything it needs to work. In the same way, there’s an EditComponent:

const EditComponent = (props) => {
  return (
    <button onClick={props.handleEdit}>
      Edit
    </button>
  );
};

Now, the render method can look like the code below:

render () {
    const view = this.state.mode === 'view';

    return (
      <div>
        <p>Text: {this.state.text}</p>

        {
          view
            ? <EditComponent handleEdit={this.handleEdit}  />
            : (
              <SaveComponent 
               handleChange={this.handleChange}
               handleSave={this.handleSave}
               text={this.state.inputText}
             />
            )
        } 
      </div>
    );
}

Here’s the complete Fiddle:

If components

Libraries like JSX Control Statements extend JSX to add conditional statements like the following:

<If condition={ a === 1 }>
  <span>Hi!</span>
</If>

This library is actually a Babel plugin, so the above code is translated to the following:

{
  a === 1 ? <span>Hi!</span> : null;
}

Alternately, the Choose tag is used for more complex conditional statements:

<Choose>
  <When condition={ a === 1 }>
    <span>One</span>
  </When>
  <When condition={ a === 2 }>
    <span>Two</span>
  </When>
  <Otherwise>
    <span>Default</span>
  </Otherwise>
</Choose>

The code above translates to the following:

{
  a === 1 ? (
    <span>One</span>
  ) : a === 2 ? (
    <span>Two</span>
  ) : (
    <span>Default</span>
  );
}

These libraries provide more advanced components, but if we need something like a simple if...else, we can use a solution similar to Michael J. Ryan’s in the comments for this issue:

const If = (props) => {
  const condition = props.condition || false;
  const positive = props.then || null;
  const negative = props.else || null;

  return condition ? positive : negative;
};

// …

render () {
    const view = this.state.mode === 'view';
    const editComponent = <EditComponent handleEdit={this.handleEdit}  />;
    const saveComponent = <SaveComponent 
               handleChange={this.handleChange}
               handleSave={this.handleSave}
               text={this.state.inputText}
             />;

    return (
      <div>
        <p>Text: {this.state.text}</p>
        <If
          condition={ view }
          then={ editComponent }
          else={ saveComponent }
        />
      </div>
    );
}

Here’s the complete Fiddle:

Enum objects

Now that the save/edit functionality is encapsulated in two components, we can use enum objects to render one of them, depending on the state of the application.

An enum is a type that groups constant values. For example, here’s how you define an enum in TypeScript:

enum State {
  Save = "Some value",
  Edit = "Another value"
}

JavaScript doesn’t support enums natively, but we can use an object to group all the properties of the enum and freeze that object to avoid accidental changes:

const State = Object.freeze({
  Save: "Some value",
  Edit: "Another value"
});

You might be wondering why we’re not using constants. The main benefit is that we can use a dynamically generated key to access the property of the object:

const key = condition ? "Save" : "Edit":
const state = State[key];

Applying this to our example, we can declare an enum object with the two components for saving and editing:

const Components = Object.freeze({
  view: <EditComponent handleEdit={this.handleEdit} />,
  edit: <SaveComponent 
          handleChange={this.handleChange}
          handleSave={this.handleSave}
          text={this.state.inputText}
        />
});

We can use the mode state variable to indicate which component to show:

const key = this.state.mode;
return (
  <div>
    <p>Text: {this.state.text}</p>
    {
      Components[key]
    } 
  </div>
);

You can see the complete code in the following fiddle:

Enum objects are a great option when you want to use or return a value based on multiple conditions, making them a great replacement for if...else and switch statements in many cases.

Higher order components in React

A higher order component (HOC) is a function that takes an existing component and returns a new one with some added functionality:

const EnhancedComponent = higherOrderComponent(component);

Applied to conditional rendering, a HOC could return a different component than the one passed based on some condition:

function higherOrderComponent(Component) {
  return function EnhancedComponent(props) {
    if (condition) {
      return <AnotherComponent { ...props } />;
    }

    return <Component { ...props } />;
  };
}

For this article, I’m going to borrow the concepts of the EitherComponent from Robin Wieruch.

In functional programming, the Either type is commonly used as a wrapper to return two different values. Let’s start by defining a function that takes two arguments, another function that will return a Boolean value, the result of the conditional evaluation, and the component that will be returned if that value is true:

function withEither(conditionalRenderingFn, EitherComponent) {

}

It’s a convention to start the name of the HOC with the word with. This function will return another function that will take the original component to return a new one:

function withEither(conditionalRenderingFn, EitherComponent) {
    return function buildNewComponent(Component) {

    }
}

The component or function returned by this inner function will be the one you’ll use in your app, so it will take an object with all the properties that it will need to work:

function withEither(conditionalRenderingFn, EitherComponent) {
    return function buildNewComponent(Component) {
        return function FinalComponent(props) {

        }
    }
}

The inner functions have access to the outer functions’ parameters. Now, based on the value returned by the conditionalRenderingFn function, you either return the EitherComponent or the original Component:

function withEither(conditionalRenderingFn, EitherComponent) {
    return function buildNewComponent(Component) {
        return function FinalComponent(props) {
            return conditionalRenderingFn(props)
                ? <EitherComponent { ...props } />
                 : <Component { ...props } />;
        }
    }
}

Or, you could use arrow functions:

const withEither = (conditionalRenderingFn, EitherComponent) => (Component) => (props) =>
  conditionalRenderingFn(props)
    ? <EitherComponent { ...props } />
    : <Component { ...props } />;

Using the previously defined SaveComponent and EditComponent, you can create a withEditConditionalRendering HOC and, with this, create an EditSaveWithConditionalRendering component:

const isViewConditionFn = (props) => props.mode === 'view';

const withEditContionalRendering = withEither(isViewConditionFn, EditComponent);
const EditSaveWithConditionalRendering = withEditContionalRendering(SaveComponent);

You can now use the HOC in the render method, passing it all the properties needed:

render () {    
    return (
      <div>
        <p>Text: {this.state.text}</p>
        <EditSaveWithConditionalRendering 
               mode={this.state.mode}
               handleEdit={this.handleEdit}
               handleChange={this.handleChange}
               handleSave={this.handleSave}
               text={this.state.inputText}
             />
      </div>
    );
}

Here’s the complete Fiddle:

Performance considerations

Conditional rendering can be tricky. As I showed you before, the performance of each option can be different. However, most of the time, the differences don’t matter a lot. But, when they do, you’ll need a good understanding of how React works with the virtual DOM and a few tricks to optimize performance.

The essential idea is that changing the position of the components due to conditional rendering can cause a reflow that will unmount/mount the components of the app. Based on the example of the article, I created two JSFiddles.

The first one uses an if...else block to show/hide the SubHeader component:


The second one uses the short circuit operator && to do the same:

Open the Inspector and click on the button a few times. You’ll see how the Content component is treated differently by each implementation.

The if...else block treats the component with the code below:

Animation Showing How the if/else Block Treats the Content Component

The short-circuit operator uses the following approach:

Animation Showing How the Short-Circuit Operator Treats the Content Component

Conditional rendering with fragments

How do you render multiple child components depending on a certain condition? The answer is by using fragments. Fragments allow you to return multiple elements by grouping them without adding an extra node to the DOM.

You can use fragments with their traditional syntax:

return (
  <React.Fragment>
    <Button />
    <Button />
    <Button />
  </React.Fragment>
);

Or their short syntax:

return (
  <>
    <Button />
    <Button />
    <Button />
  </>
);

When it comes to rendering multiple elements with fragments depending on a condition, you can use any of the techniques described in this article. For example, you could use the ternary operator this way:

{ 
  view
  ? null
  : (
    <React.Fragment>
      <Button />
      <Button />
      <Button />
    </React.Fragment>
  )
}

Better yet, you could use a short-circuit &&:

{ 
  condition &&
  <React.Fragment>
    <Button />
    <Button />
    <Button />
  </React.Fragment>
}

You could also encapsulate the rendering of the child elements in a method and use an if or switch statement to decide what to return:

render() {
  return <div>{ this.renderChildren() }</div>;
}

renderChildren() {
  if (this.state.children.length === 0) {
    return <p>Nothing to show</p>;
  } else {
    return (
      <React.Fragment>
        {this.state.children.map(child => (
          <p>{child}</p>
        ))}
      </React.Fragment>
    );
 }
}

Conditional rendering with React Hooks

Nowadays, most experienced React developers use Hooks to write components. So, instead of having a class like the following:

import React, { Component } from 'react';

class Doubler extends Component {
  constructor(props) {
    super(props);

    this.state = {
      num: 1,
    };
  }

  render() {
    return (
      <div>
        <p>{this.state.num}</p>
        <button onClick={() =>
            this.setState({ num: this.state.num * 2 })
        }>
          Double
        </button>
      </div>
    );
  }
}

You can write the component with a function using the useState Hook:

import React from 'react';

function Doubler() {
  const [num, setNum] = React.useState(1);

  return (
    <div>
      <p>{num}</p>
      <button onClick={() => setNum(num * 2)}>
        Double
      </button>
    </div>
  );
}

Just like fragments, you can use any of the techniques described in this article to conditionally render a component that uses Hooks:

function Doubler() {
  const [num, setNum] = React.useState(1);
  const showButton = num <= 8;
  const button = <button onClick={() => setNum(num * 2)}>Double</button>;

  return (
    <div>
      <p>{num}</p>
      {showButton && button}
    </div>
  );
}

The only caveat is that you can’t conditionally call a Hook so that it isn’t always executed. According to the Hooks documentation, you shouldn’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.

With the useEffect Hook, you can’t put a condition that could prevent the Hook from being called every time the component is rendered, like this:

if (shouldExecute) {
  useEffect(() => {
    // ...
  }
}

You have to put the condition inside the Hook:

useEffect(() => {
  if (shouldExecute) {
    // ...
  }
}, [shouldExecute])

What’s the best way to implement conditional rendering in React?

As with many things in programming, there are many ways to implement conditional rendering in React. I’d say that, with the exception of the first method, if...else with many returns, you’re free to choose whatever method you want.

Some factors to include in your decision include your programming style, how complex the conditional logic is, and how comfortable you are with JavaScript, JSX, and advanced React concepts like HOCs.

And, all things equal, you should always favor simplicity and readability. I hope you enjoyed this article, and be sure to leave a comment if you have any questions.

Esteban Herrera Family man. Java and JavaScript developer. Swift and VR/AR hobbyist. Like books, movies, and still trying many things. Find me at eherrera.net

4 Replies to “React conditional rendering: 9 methods with examples”

  1. Nice article!

    Why do you still use class components? It’s 2020, function components with hooks are not an “alternative” way. They are THE way to go and classes are unnecessary for the examples you show.

    Your article is a great resource for beginner React developers, but also confusing, because you use class components.

    1. This post was originally published several years ago, before the stable release of the Hooks API, and we just updated it a few months back. We’ve added an editor’s note to clarify. Thanks for keeping us honest.

  2. Althought this article has inmense value and all of this is valid React, when an application gets big, using live vanilla javascript to condition the render adds complexity and you start building an enviroment very prone to errors later, good practice will be create a component that handles the condition taking it as a prop and returns the children or null, and reuse it across the app, making your render entirely declarative instead of imperative… has been an old trade in San Francisco since the begining of React.. truth is you can call it how ever you want,, but make sure the component do that.. back in the pre-hooks days ppl use to do it using a HOC ….

Leave a Reply