State & InteractionBeginner7 min06 / 9

Conditional Rendering

Learn how to show, hide, or swap pieces of UI in React based on state — using &&, the ternary operator, and early returns.

Most apps don't look the same every second. A login page disappears once you sign in. An error message appears only when something goes wrong. A loading spinner shows while data is fetching, then vanishes the moment it arrives.

This is conditional rendering — the ability to show or hide parts of your UI based on some condition. In React it isn't a special feature you have to learn separately; it's just JavaScript, used right inside your JSX. Once it clicks, you'll wonder how you ever built UIs without it.

Think of it like

A Velvet Rope at a Club

Think of conditional rendering like a bouncer with a velvet rope. The bouncer checks a condition — "Are you on the list?" If yes, you get in (the element renders). If no, you stay outside (nothing renders). The rope itself is invisible to the people who sail through. Your UI works exactly the same way — only the elements that pass the condition make it onto the screen.

#Pattern 1: && for Show or Hide

The `&&` operator renders its right side when the left is truthy, and renders nothing when it is falsy. Use it for show-or-nothing situations.
function Inbox({ unreadCount }) {
  return (
    <div>
      <h2>Inbox</h2>
      {unreadCount > 0 && (
        <p className="badge">{unreadCount} unread messages</p>
      )}
    </div>
  );
}
Common mistake

Watch Out for 0

0 is falsy — but React will render the digit 0 on screen instead of nothing. This catches everyone at least once.

```jsx // BUG: renders "0" when items.length is 0 {items.length && <List items={items} />}

// SAFE: compare explicitly {items.length > 0 && <List items={items} />} ```

Whenever the left side of && might be a number, add a > 0 comparison to convert it to a proper boolean.

#Pattern 2: Ternary for Either/Or

The ternary `condition ? valueIfTrue : valueIfFalse` lets you swap text, elements, or whole blocks of markup. Wrap multi-line branches in parentheses to keep things readable.
function UserCard({ isLoggedIn, username }) {
  return (
    <div>
      {isLoggedIn ? (
        <p>Welcome back, {username}!</p>
      ) : (
        <p>Please sign in to continue.</p>
      )}
      <button>{isLoggedIn ? 'Log out' : 'Log in'}</button>
    </div>
  );
}

#Pattern 3: Early Return

Return early (with null or a fallback) before reaching the main JSX. Guard clauses at the top keep the happy path clean and unindented — and you can stack as many as you need.
function Profile({ user, isLoading }) {
  if (isLoading) return <p>Loading...</p>;
  if (!user) return <p>No user found.</p>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.bio}</p>
    </div>
  );
}

#Putting It Together: Rendering Based on State

Conditional rendering becomes really powerful when the condition is a piece of state. Changing state triggers a re-render, and the component recalculates which JSX to return — so the UI updates automatically, with no manual DOM work.

State drives the condition; the ternary drives the output. One click, two completely different UIs.
import { useState } from 'react';

function Spoiler({ text }) {
  const [revealed, setRevealed] = useState(false);

  return (
    <div>
      {revealed ? (
        <p>{text}</p>
      ) : (
        <p style={{ filter: 'blur(6px)' }}>Hidden</p>
      )}
      <button onClick={() => setRevealed(prev => !prev)}>
        {revealed ? 'Hide' : 'Reveal'}
      </button>
    </div>
  );
}
Tip

Extract Complex Conditions

If your condition involves several checks, pull it into a named variable above the return — it keeps your JSX readable and makes the logic easy to scan.

``jsx const showWelcome = isLoggedIn && user !== null && !user.isBanned; return <div>{showWelcome && <WelcomeBanner />}</div>; ``

Quick check

You want to render a <Sale /> component only when a boolean `isSaleActive` is true, and render nothing otherwise. Which pattern is most appropriate?

Key takeaways

  • Use `condition && <Element />` to show something or render nothing — always use `> 0` comparisons when the condition might be a number, to avoid accidentally rendering `0`.
  • Use `condition ? <A /> : <B />` to swap between two different elements, labels, or whole sections of markup.
  • Use an early `return null` (or a fallback) at the top of a component to bail out before the main UI when data is missing, loading, or in an error state.
  • Pairing conditional rendering with state means your UI updates automatically whenever the underlying data changes — no manual DOM work needed.
  • When conditions grow complex, extract them into clearly-named variables above your `return` statement to keep JSX readable.
Practice challenges
Test yourself · earn XP
0/4
Fix the bug#1

This code has a bug — what's wrong?

fix-bug
function Cart({ items }) {
  return (
    <div>
      <h2>Cart</h2>
      {items.length && <p>You have items!</p>}
    </div>
  );
}
Fill in the blank#2

Complete this show-or-nothing pattern: render the badge ONLY when unreadCount is greater than zero, and render nothing otherwise. Fill in the operator that renders its right side only when the left side is truthy.

function Inbox({ unreadCount }) {
  return (
    <div>
      <h2>Inbox</h2>
      {unreadCount > 0  <p>{unreadCount} unread</p>}
    </div>
  );
}
Reorder the lines#3

Arrange these lines into a correct Profile component that uses early-return guard clauses: show a loading message while fetching, a fallback if there is no user, then the profile card otherwise.

1
  );
2
  if (isLoading) return <p>Loading...</p>;
3
}
4
    <div><h2>{user.name}</h2></div>
5
function Profile({ user, isLoading }) {
6
  return (
7
  if (!user) return <p>No user found.</p>;
Predict the output#4

The Spoiler component starts with revealed = false. What is on screen BEFORE the user clicks anything?

predict-output
function Spoiler({ text }) {
  const [revealed, setRevealed] = useState(false);
  return (
    <div>
      {revealed ? <p>{text}</p> : <p>Hidden</p>}
      <button onClick={() => setRevealed(prev => !prev)}>
        {revealed ? 'Hide' : 'Reveal'}
      </button>
    </div>
  );
}
Your turn
Practice exercise

Build a PasswordInput component. It should render a text input and a toggle button. When the button is clicked, it switches the input between type="password" (text hidden) and type="text" (text visible). The button label should say "Show" when the password is hidden and "Hide" when it is visible.

Try it live — edit the code and hit Run to see it rendered:

solution.jsx · editable