react-renderizado-condicional

Conditional Rendering in React

  • 5 min

Conditional rendering consists of showing or not showing content based on a logical or boolean condition.

For example, if we want to show a welcome message only if the user is authenticated.

In React, this is achieved using normal control structures from JavaScript, such as if, else, ternary or logical operators, within the JSX code.

However, inside the curly braces {} of JSX we can only use expressions (code that returns a value), so we cannot use block statements like if or switch directly inside them.

So, how do we do it? We have different options depending on the case (as always, let’s go).

  • AND (&&): To optionally show something if a condition is met.
  • Ternary (?): To toggle between two visual states (Show/Hide, Login/Logout).
  • Early Return (if): To block the entire rendering (Loading, Errors, Permissions).

The Ternary Operator ?

Inside the curly braces {} of JSX we cannot put an if/else (because they don’t return anything).

The first option for conditional rendering in React is the Ternary Operator.

It’s perfect for “One thing or Another” logic.

// Structure: condition ? true : false

function UserPanel({ isLogged }) {
  return (
    <div>
      {isLogged ? (
        <button>Log Out</button>
      ) : (
        <button>Log In</button>
      )}
    </div>
  );
}
Copied!

If the code block is large, use parentheses () after the ? and : to be able to indent the JSX across multiple lines and improve readability.

The AND Operator &&

Sometimes we don’t want to show “this or that”. Sometimes we only want to show a component if the condition is true, and if not, show nothing.

We could use a ternary returning null (condition ? <Something/> : null), but it’s quite messy.

For this, it’s very common to take advantage of the short-circuit behavior of the logical AND operator (&&).

This leverages that, in JavaScript,

  • true && expression evaluates to expression
  • false && expression evaluates to false.

React is smart enough to render nothing if it receives false, null, or undefined, so we can use it for conditional rendering.

function Messages({ newMessages }) {
  return (
    <div>
      <h1>Inbox</h1>
      
      {/* Only shown if there are messages */}
      {newMessages.length > 0 && (
        <span className="badge">
          You have unread messages
        </span>
      )}
    </div>
  );
}
Copied!

Flow Control with IF

We said that if cannot be used inside JSX. But we can use it before the return.

For example, sometimes we want to avoid rendering the entire component if something is missing. In these cases, we use normal if statements to cut off execution. This is known as the Early Return pattern.

function UserProfile({ user, isLoading }) {
  // 1. If it's loading, we return this and finish
  if (isLoading) {
    return <div>Loading profile...</div>;
  }

  // 2. If there is no user (it's null), we return error or nothing
  if (!user) {
    return null; // Rendering null paints nothing in the DOM
  }

  // 3. If we get here, we have data and are not loading
  return (
    <div className="profile">
      <h1>{user.name}</h1>
      <p>{user.bio}</p>
    </div>
  );
}
Copied!

This pattern makes the final JSX (return (...)) cleaner, especially if the alternative was to nest too many ternaries.

Render Functions

If you need complex logic for only a small part of the component (not for the whole thing), the previous option might force you to duplicate a lot of code. Meanwhile, the ternaries we saw tend to become unreadable if we nest many.

Here the best practice is to extract that logic into a helper function. Being a normal JavaScript function (outside the JSX, outside the {}), here we can use if, else or switch normally.

function OrderStatus({ status }) {
  
  const renderIcon = () => {
    switch(status) {
      case 'shipped': return <TruckIcon />;
      case 'delivered': return <CheckIcon />;
      case 'cancelled': return <CrossIcon />;
      default: return <ClockIcon />;
    }
  };

  return (
    <div className="order-card">
      {/* We call the function to get the resulting JSX */}
      {renderIcon()}
      <span>Status: {status}</span>
    </div>
  );
}
Copied!

Although it works, it might be preferable to create sub-components (<OrderIcon status={status} />) to keep the main component clean. But it’s a useful tool, it depends on the case.