React Conditional Rendering: if, Ternary, and Logical Operators

Learn React Conditional Rendering: if, Ternary, and Logical Operators with practical examples, explanations, best practices, and real-world coding techniques.

Introduction to Conditional Rendering

Conditional rendering in React means displaying different elements or components depending on the current state, props, or other conditions. It allows an interface to respond to user interactions, authentication status, loading progress, permissions, and the availability of data.

React uses JavaScript expressions to determine what a component returns. You can use familiar JavaScript constructs such as if, the ternary operator, logical AND (&&), and switch statements to decide which UI should appear.

Using if Statements

An if statement is useful when a component needs to return completely different content based on a condition. Evaluate the condition before the main JSX and return the appropriate component or element.

function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h2>Welcome back!</h2>;
  }

  return <h2>Please sign in.</h2>;
}

export default Greeting;

When isLoggedIn is true, React renders the welcome message. Otherwise, it renders the sign-in message. Early returns can make more complicated components easier to read by handling special cases first.

Using the Ternary Operator

The ternary operator is a concise way to choose between two expressions directly inside JSX. It is particularly useful for short conditional elements.

function AccountStatus({ isActive }) {
  return (
    <div>
      <p>
        {isActive ? 'Account active' : 'Account inactive'}
      </p>

      {isActive ? (
        <button>Open dashboard</button>
      ) : (
        <button>Activate account</button>
      )}
    </div>
  );
}

export default AccountStatus;

The expression before the question mark is evaluated as the condition. The expression before the colon is selected when the condition is truthy, and the expression after the colon is selected otherwise.

Avoid deeply nested ternary operators because they can make UI logic difficult to follow. For several distinct states, consider using an if statement or a switch statement instead.

Using Logical AND

The logical AND operator is useful when an element should appear only if a condition is true. If the left operand is falsy, JavaScript returns that operand; otherwise, it evaluates and returns the right operand.

function Notification({ hasMessage }) {
  return (
    <div>
      <h2>Notifications</h2>
      {hasMessage && (
        <p>You have a new notification.</p>
      )}
    </div>
  );
}

export default Notification;

When hasMessage is true, React renders the paragraph. When it is false, the expression evaluates to false and React renders nothing for that expression.

Be careful when the condition is a number. An expression such as count && <p>Items available</p> can render the number 0 when count is zero. If zero should display nothing, use an explicit comparison such as count > 0 && ....

Using a Switch Statement

A switch statement works well when the UI depends on several possible values, such as request status, subscription level, or the current step in a workflow. Put the statement in a function and return the corresponding JSX.

function OrderStatus({ status }) {
  switch (status) {
    case 'pending':
      return <p>Your order is being processed.</p>;

    case 'shipped':
      return <p>Your order is on its way.</p>;

    case 'delivered':
      return <p>Your order has arrived.</p>;

    default:
      return <p>Order status unavailable.</p>;
  }
}

export default OrderStatus;

Each case handles a distinct state, and the default branch provides a fallback for values that are not recognized. Returning from each case avoids accidental fall-through and makes the result explicit.

Conditional Rendering with Early Returns

Early returns are especially useful when a component has loading, error, empty, and success states. Handling these states before the main content keeps the normal rendering path straightforward.

function ProductDetails({ product, loading, error }) {
  if (loading) {
    return <p>Loading product...</p>;
  }

  if (error) {
    return <p role="alert">Unable to load product.</p>;
  }

  if (!product) {
    return <p>Product not found.</p>;
  }

  return (
    <article>
      <h2>{product.name}</h2>
      <p>Price: {product.price}</p>
    </article>
  );
}

export default ProductDetails;

Each early return handles one distinct state, leaving the final JSX for the successful case. This pattern is common in dashboards, detail pages, search results, and API-driven components.

See React API Fetching for examples of managing asynchronous data.

Rendering Based on User Permissions

Conditional rendering can adapt an interface to the current user's role or permissions. For example, an administrative action may be shown only to users whose role allows it.

function DashboardActions({ role }) {
  return (
    <div>
      <button>View profile</button>

      {role === 'admin' && (
        <button>Manage users</button>
      )}
    </div>
  );
}

export default DashboardActions;

This example changes what appears in the UI, but it does not enforce security. The backend must independently verify the user's permissions before performing sensitive operations. Client-side conditions can always be bypassed or modified by a user.

Combining Multiple Conditions

JavaScript logical operators can combine conditions when rendering depends on more than one value. Use parentheses to make the intended logic clear, particularly when combining AND (&&) and OR (||).

function CourseAccess({ isLoggedIn, hasSubscription }) {
  const canAccess = isLoggedIn && hasSubscription;

  return (
    <section>
      {canAccess ? (
        <p>You can access this course.</p>
      ) : (
        <p>Sign in and subscribe to continue.</p>
      )}
    </section>
  );
}

export default CourseAccess;

Naming a meaningful condition such as canAccess makes the JSX easier to understand. It also allows the same condition to be reused consistently in the component.

Showing and Hiding Elements

You can conditionally include an element in the render output or keep it mounted and change its visibility. These approaches have different effects on component state, accessibility, and layout.

Conditionally include an element

{isOpen && <div>Panel content</div>}

When isOpen becomes false, the panel is removed from the React tree. Components inside it may unmount and lose their local state.

Keep an element mounted and change visibility

<div hidden={!isOpen}>
  Panel content
</div>

The element remains in the DOM while the hidden attribute controls its visibility. Its descendant components remain mounted, so their local state is generally preserved. Choose the approach that matches the required behavior and accessibility needs.

Conditional Rendering with Lists

A component can render a list when data exists and display a fallback message when the list is empty. This provides a better experience than showing a blank area without explanation.

function CourseList({ courses }) {
  if (courses.length === 0) {
    return <p>No courses are available.</p>;
  }

  return (
    <ul>
      {courses.map((course) => (
        <li key={course.id}>{course.title}</li>
      ))}
    </ul>
  );
}

export default CourseList;

The example assumes courses is always an array. If the data might not have loaded yet, represent that state separately or provide a suitable default. Each item also needs a stable key so React can track list entries across updates.

Learn more about list rendering and stable keys in React Lists and Keys.

Using Conditional Rendering with State

State lets a component change what it renders in response to user interactions. A common example is a toggle button that shows or hides additional information.

import { useState } from 'react';

function DetailsPanel() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <section>
      <button
        type="button"
        aria-expanded={isVisible}
        onClick={() => setIsVisible((current) => !current)}
      >
        {isVisible ? 'Hide details' : 'Show details'}
      </button>

      {isVisible && (
        <div>
          <h2>Additional information</h2>
          <p>This content appears when the panel is open.</p>
        </div>
      )}
    </section>
  );
}

export default DetailsPanel;

The functional state update uses the previous value to calculate the next value. The aria-expanded attribute communicates the current expanded state to assistive technologies.

Explore React State to understand how state updates cause components to render again.

Common Conditional Rendering Mistakes

Rendering zero with logical AND

Expressions such as items.length && ... can render the number zero when the list is empty. Use items.length > 0 && ... to make the intended condition explicit.

Nesting too many ternary operators

Long chains of nested ternaries make conditions difficult to understand and maintain. Extract complex logic into variables, helper functions, or early returns.

Confusing hidden content with removed content

Removing a component can reset its local state, while hiding a mounted element generally preserves that state. Choose based on whether the component should remain active.

Using UI conditions as access control

Hiding an administrative button is not a security boundary. Always enforce permissions in the backend for protected data and operations.

Ignoring loading and error states

Data-driven interfaces should distinguish loading, success, empty, and failure states instead of treating missing data as a single condition.

Choosing the Right Technique

Technique Best suited for
if statement Early returns and larger conditional branches.
Ternary operator Choosing between two expressions inside JSX.
Logical AND Displaying an element only when a condition is true.
switch statement Handling several distinct status or category values.
Early return Separating loading, error, empty, and success states.

Key Takeaway

Conditional rendering lets React interfaces respond to data, state, props, and user permissions. Use the simplest JavaScript technique that makes each condition clear, handle loading and error states explicitly, and remember that hiding UI elements does not replace server-side security checks.

Code Examples

function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h2>Welcome back!</h2>;
  }

  return <h2>Please sign in.</h2>;
}

export default Greeting;
    
function AccountStatus({ isActive }) {
  return (
    <div>
      <p>{isActive ? "Account active" : "Account inactive"}</p>
      {isActive ? (
        <button>Open dashboard</button>
      ) : (
        <button>Activate account</button>
      )}
    </div>
  );
}

export default AccountStatus;
    
function Notification({ hasMessage }) {
  return (
    <div>
      <h2>Notifications</h2>
      {hasMessage && <p>You have a new notification.</p>}
    </div>
  );
}

export default Notification;
    
function OrderStatus({ status }) {
  switch (status) {
    case "pending":
      return <p>Your order is being processed.</p>;
    case "shipped":
      return <p>Your order is on its way.</p>;
    case "delivered":
      return <p>Your order has arrived.</p>;
    default:
      return <p>Order status unavailable.</p>;
  }
}

export default OrderStatus;
    
import { useState } from "react";

function DetailsPanel() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <section>
      <button
        type="button"
        aria-expanded={isVisible}
        onClick={() => setIsVisible(current => !current)}
      >
        {isVisible ? "Hide details" : "Show details"}
      </button>
      {isVisible && (
        <div>
          <h2>Additional information</h2>
          <p>This content appears when the panel is open.</p>
        </div>
      )}
    </section>
  );
}

export default DetailsPanel;
    

Pro Tip

Choose conditional rendering based on readability: use early returns for loading and error states, ternaries for simple two-way choices, and logical AND for optional elements. Always check numeric conditions explicitly to avoid accidentally rendering zero.

🎨 IgKnight Docs

Master HTML, CSS, JS, Python, .NET and more with easy-to-follow lessons and practical code examples.

© 2025 IgKnight Learning Platform. All rights reserved.