Conditional rendering is a powerful feature in React that allows developers to render components based on certain conditions.

It is a fundamental concept that plays a crucial role in building dynamic and interactive web applications.

In this comprehensive guide, we will dive deep into conditional rendering in React, covering basic and advanced techniques with examples for proper understanding.

Understanding Conditional Rendering in React

Conditional rendering in React allows developers to dynamically control what content is displayed on the screen based on specific values which can be stored in a variable, state, or props.

This can be extremely useful in scenarios where you want to show or hide certain UI elements, change the layout of a page, or render different content based on user interactions.

Conditional rendering is important in React applications because it enables you to create dynamic and interactive user interfaces that can respond to changing data and user interactions in real time.

It will help improve the performance and efficiency of your applications by avoiding unnecessary rendering of components or elements that are not needed.

Basic Techniques for Conditional Rendering

There are several basic techniques that you can use for conditional rendering in React. Let’s explore each of them in detail.

Using the if Statement for Conditional Rendering

One of the most straightforward ways to implement conditional rendering in React is by using the traditional if statement.

if (condition) {
    return <p>Expression 1</p>;
  } else {
    return <p>Expression 2</p>;
  }

The JavaScript’s if statement can be used inside your component’s render() method to conditionally render content based on a certain condition.

For example, you can use the if statement to display a loading spinner while waiting for data to load:

import { useState, useEffect } from 'react';
import Spinner from './Spinner';

const MyComponent = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    // Fetch data from an API
    fetch('https://example.com/data')
      .then((response) => response.json())
      .then((data) => {
        setData(data);
        setIsLoading(false);
      });
  }, []);

  if (isLoading) {
    return <Spinner />;
  }

  return <div>{/* Render the data here */}</div>;
};

export default MyComponent;

In this example, MyComponent fetches data from an API using the useEffect hook. While waiting for the data to load, we display a Spinner component using the if statement.

Another example can be rendering a fallback UI when an error occurs while rendering your component:

const MyComponent = ({ data }) => {
  if (!data) {
    return <p>Something went wrong. Please try again later.</p>;
  }

  return <div>{/* Render the data here */}</div>;
};

export default MyComponent;

In this code, we have a MyComponent that takes a data prop. If the data prop is falsy, we render an error message using the if statement.

Finally, you can display different content for different user roles with the if statement:

const MyComponent = ({ user }) => {
  if (user.role === 'admin') {
    return <p>Welcome, admin!</p>;
  } else if (user.role === 'user') {
    return <p>Welcome, user!</p>;
  } else {
    return <p>You are not authorized to access this page.</p>;
  }
};

export default MyComponent;

In this code, we have a MyComponent that takes a user prop. Depending on the user.role property, we display different content using the if statement.

Using the Ternary Operator for Conditional Rendering

Another concise way to implement conditional rendering in React is by using the ternary operator (?) inside JSX.

The ternary operator allows you to write a compact inline if-else statement by specifying 3 operands. The first operand is the condition, while the other two operands are the expressions. If the condition is true, the first expression will be executed; otherwise, the second expression.

For example, you can render different components based on a prop:

import ComponentA from './ComponentA';
import ComponentB from './ComponentB';

const ExampleComponent = ({ shouldRenderComponentA }) => {
  return (
    <div>
      {shouldRenderComponentA ? <ComponentA /> : <ComponentB />}
    </div>
  );
};

export default ExampleComponent;

In this code, we have an ExampleComponent that takes a prop called shouldRenderComponentA. We use the ternary operator to conditionally render either ComponentA or ComponentB based on the prop value.

You can also render different text based on a state:

import { useState } from 'react';

const ExampleComponent = () => {
  const [showMessage, setShowMessage] = useState(false);

  return (
    <div>
      <button onClick={() => setShowMessage(!showMessage)}>
        {showMessage ? 'Hide message' : 'Show message'}
      </button>
      {showMessage ? <p>Hello, world!</p> : null}
    </div>
  );
};

export default ExampleComponent;

In this example, we use the ternary operator to conditionally render different text depending on the value of the showMessage state. When the button is clicked, the value of showMessage is toggled, and the text is displayed or hidden accordingly.

Finally, you can render a loading spinner while data is being fetched:

import { useState, useEffect } from 'react';
import Spinner from './Spinner';

const ExampleComponent = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const jsonData = await response.json();
      setData(jsonData);
      setIsLoading(false);
    };
    fetchData();
  }, []);

  return (
    <div>
      {isLoading ? <Spinner /> : <p>{data.title}</p>}
    </div>
  );
};

export default ExampleComponent;

In this example, we use the ternary operator to conditionally render a loading spinner while data is being fetched from an API. Once the data is available, we render the title property using the ternary operator.

Using Logical AND and OR Operators for Conditional Rendering

You can also use the logical AND (&&) and OR (||) operators to implement conditional rendering in React.

The logical AND operator allows you to render a component only if a certain condition is true, while the logical OR operator allows you to render a component if either of the conditions is true.

These operators are useful when you have simple conditions that determine whether a component should be rendered or not. For example, if you want to render a button only if a form is valid, you can use the logical AND operator like this:

import { useState } from 'react';

const FormComponent = () => {
  const [formValues, setFormValues] = useState({ username: "", password: "" });

  const isFormValid = formValues.username && formValues.password;

  const handleSubmit = (event) => {
    event.preventDefault();
    // Submit form data
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={formValues.username}
        placeholder="Type Username..."
        onChange={(e) =>
          setFormValues({ ...formValues, username: e.target.value })
        }
      />
      <br />
      <input
        type="password"
        value={formValues.password}
        placeholder="Type Password..."
        onChange={(e) =>
          setFormValues({ ...formValues, password: e.target.value })
        }
      />
      {isFormValid && <button type="submit">Submit</button>}
    </form>
  );
};

export default FormComponent;

In this example, we have a FormComponent that has a form with two input fields for username and password. We’re using useState hook to manage the form values and isFormValid variable to check if both input fields have values. Using the logical AND operator (&&), we render the submit button only if isFormValid is true. This ensures that the button is only enabled when the form is valid.

Similarly, you can use the OR operator to render a loading message if data is still loading or an error message if an error occurs:

import React, { useEffect, useState } from 'react';

const DataComponent = () => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [errorMessage, setErrorMessage] = useState('');

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        setData(data);
      } catch (error) {
        setErrorMessage('An error occurred while fetching data.');
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, []);

  return (
    <>
      {errorMessage || isLoading ? (
        <p>{errorMessage || 'Loading...'}</p>
      ) : (
        <ul>
          {data.map((item) => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}
    </>
  );
};

export default DataComponent;

In this example, a DataComponent fetches data from an API using fetch and displays it in a list. We’re using useState hook to manage the data, loading state, and error message. Using the logical OR operator (||), we can render a loading message or an error message if either of its conditions is true. This ensures that the user sees a message indicating the current state of the data fetching process.

Using the logical AND and OR operators for conditional rendering in React is a concise and readable way to handle simple conditions. However, it’s better to use other approaches like switch statements for more complex logic.

Advanced Techniques for Conditional Rendering

Conditional rendering in React can be more complex depending on the requirements of your application. Here are some advanced techniques that you can use for conditional rendering in more complex scenarios.

Using Switch Statements for Conditional Rendering

While if statements and ternary operators are common approaches for conditional rendering, sometimes a switch statement can be more appropriate, especially when dealing with multiple conditions.

Here’s an example:

import React from 'react';
const MyComponent = ({ userType }) => {
  switch (userType) {
    case 'admin':
      return <p>Welcome, admin user!</p>;
    case 'user':
      return <p>Welcome, regular user!</p>;
    default:
      return <p>Please log in to continue.</p>;
  }
};
export default MyComponent;

In this code, a switch statement is used to render content based on the userType prop conditionally. This approach can be helpful when dealing with multiple conditions and provides a more organized and readable way to handle complex logic.

Conditional Rendering With React Router

React Router is a popular library for handling client-side routing in React applications. React Router allows you to render components based on the current route conditionally.

Here’s an example of implementing conditional rendering using React Router:

import { useState } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

import Home from './components/Home';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
import NotFound from './components/NotFound';

const App = () => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/login">
          <Login setIsLoggedIn={setIsLoggedIn} />
        </Route>
        {isLoggedIn ? (
          <Route path="/dashboard" component={Dashboard} />
        ) : (
          <Route component={NotFound} />
        )}
      </Switch>
    </Router>
  );
};

export default App;

In this code, we are using the isLoggedIn state to conditionally render either the Dashboard component if the user is logged in, or the NotFound component if the user is not logged in. The Login component sets the isLoggedIn state to true once the user successfully logs in.

Note that we are using the <Route> component’s children prop to pass in the Login component and the setIsLoggedIn function. This allows us to pass in props to the Login component without specifying it in the path prop.

Summary

Conditional rendering is a powerful technique in React that allows you to dynamically update the UI based on different conditions.

Depending on the complexity of your application’s UI logic, you can choose the approach that best fits your needs.

Remember to keep your code clean, organized, and readable, and always thoroughly test your conditional rendering logic to ensure it works as expected in different scenarios.

Looking for the ideal hosting solution for your React applications? Give Kinsta’s Application hosting a try for free!

Joel Olawanle Kinsta

Joel is a Frontend developer working at Kinsta as a Technical Editor. He is a passionate teacher with love for open source and has written over 300 technical articles majorly around JavaScript and it's frameworks.