React

Conditional Rendering in React

Thirdy Gayares
10 min read

🎓 What You Will Learn

  • The && operator: render something only when a condition is truthy
  • Ternaries: pick between two pieces of UI inline
  • Early returns: handle loading/error/empty states with guard clauses
  • Object lookup / switch: map a value to UI without an if/else chain
  • The falsy gotcha: why {count && <p>...</p>} can render a stray 0
  • Rendering nothing: using null on purpose
1

Why Conditional Rendering Matters

Almost every real component needs to show different UI depending on state: a spinner while data loads, an error message when a request fails, a login button vs. a profile menu. In plain HTML you'd need separate pages. In React, it's just JavaScript — if,&&, and ternaries decide what gets rendered.

There's no special "React conditional syntax" to memorize. JSX is just JavaScript expressions wrapped in curly braces, so any expression that evaluates to a React node (or null) can be rendered.

2

The && Operator — Render When True

The most common pattern: render something only if a condition is truthy, and render nothing otherwise. JavaScript's && short-circuits — if the left side is falsy, it returns the left side without evaluating the right side.

and-operator.jsx
function Notification({ hasUnread }) {
  return (
    <div>
      {/* If hasUnread is truthy, render the badge. Otherwise render nothing */}
      {hasUnread && <span className="badge">New</span>}
    </div>
  );
}

Nothing to show yet — try the buttons above.

3

The Ternary — Choosing Between Two Outcomes

When you need to show one thing or another (not "something or nothing"), reach for the ternary operator: condition ? ifTrue : ifFalse.

ternary.jsx
function LoginButton({ loggedIn, onClick }) {
  return (
    <button onClick={onClick}>
      {loggedIn ? "Log out" : "Log in"}
    </button>
  );
}
You're not subscribed yet.
Rule of thumb: use && for "show this or show nothing." Use a ternary for "show this or show that." Reaching for the wrong one is usually what makes conditional JSX hard to read.
4

Early Returns — Guard Clauses for Bigger Components

Once a component has to handle loading, error, empty, and success states, nested ternaries inside JSX turn into a wall of ? :. The cleaner fix: return early from the function before you even get to the main JSX.

early-return-bad.jsx
// ❌ Gets hard to read fast — nested ternaries
return (
  <div>
    {status === "loading" ? (
      <Spinner />
    ) : status === "error" ? (
      <ErrorMessage />
    ) : users.length === 0 ? (
      <EmptyState />
    ) : (
      <UserList users={users} />
    )}
  </div>
);
  • Alice
  • Bob
  • Charlie
Why this is better: each state gets its own clearly readable if block, and the "happy path" JSX at the bottom of the function only has to deal with the success case.
5

Object Lookup — Replacing a Long if/else Chain

When a value maps to one of several known outcomes (an order status, a user role, an HTTP error code), an if/else chain or switch works, but a plain object lookup is usually shorter and easier to extend — add one more key, not one more branch.

⏳ Pending
When to still use switch: if a branch needs to run side effects or multiple statements (not just return a value), a switch statement is clearer than cramming logic into an object lookup.
6

The Falsy Gotcha — Why You See a Stray 0

&& returns whichever side it stops at. If the left side is 0, && returns 0 — and React renders 0, because 0 is a valid, visible value (unlike false, null, or undefined, which React silently skips).

falsy-gotcha.jsx
function CartSummary({ cartCount }) {
  return (
    <div>
      {/* ❌ If cartCount is 0, this renders a literal "0" on the page */}
      {cartCount && <p>{cartCount} items in cart</p>}

      {/* ✅ Force a real boolean first */}
      {cartCount > 0 && <p>{cartCount} items in cart</p>}

      {/* ✅ Or use a ternary, which always resolves to one branch */}
      {cartCount > 0 ? <p>{cartCount} items in cart</p> : null}
    </div>
  );
}
Common mistake: {items.length && <List items={items} />} renders a bare 0 when the list is empty. Always compare with > 0, !== 0, or convert with Boolean(...) before using && on a number.
7

Rendering Nothing on Purpose

Sometimes the correct output is nothing. Returning null from a component tells React "render no DOM here" — it's not an error, it's a valid, intentional choice.

render-null.jsx
function Banner({ dismissed, message }) {
  if (dismissed) {
    return null; // Nothing rendered — perfectly valid
  }

  return <div className="banner">{message}</div>;
}
8

Common Mistakes

1Rendering a stray 0 or empty string
mistake-falsy.jsx
// ❌ BAD: renders "0" when count is 0
{count && <Badge count={count} />}

// ✅ GOOD: always resolves to a boolean
{count > 0 && <Badge count={count} />}
2Nesting too many ternaries in JSX
mistake-nested-ternary.jsx
// ❌ BAD: unreadable past 2 branches
{a ? <A /> : b ? <B /> : c ? <C /> : <D />}

// ✅ GOOD: early returns, or an object/switch lookup
if (a) return <A />;
if (b) return <B />;
if (c) return <C />;
return <D />;
3Forgetting a key case entirely
mistake-missing-case.jsx
// ❌ BAD: no "error" branch — errors silently render nothing
if (status === "loading") return <Spinner />;
return <UserList users={users} />;

// ✅ GOOD: every known state is handled explicitly
if (status === "loading") return <Spinner />;
if (status === "error") return <ErrorMessage />;
return <UserList users={users} />;
9

Best Practices

Use && for "something or nothing," ternary for "this or that"
Always compare numbers explicitly (count > 0) before &&
Reach for early returns once you have 3+ possible UI states
Use an object lookup instead of a long if/else for value → UI mapping
Return null intentionally — it's a valid, readable "render nothing"
10

Pattern Reference

PatternUse WhenExample
&&Show something or nothing{isAdmin && <AdminPanel />}
TernaryShow one of two things{loggedIn ? <Menu /> : <LoginBtn />}
Early return3+ distinct UI statesif (loading) return <Spinner />;
Object lookupMap a value to UI/configSTATUS_MAP[status]
Return nullIntentionally render nothingif (hidden) return null;
11

Practice Project

Build a small notification center component that:

  • Shows a "You're all caught up!" message when there are 0 notifications
  • Shows a badge with the count when there's 1 or more (watch the falsy gotcha!)
  • Uses early returns for loading and error states
  • Uses an object lookup to render a different icon per notification type
12

What's Next?

🚀 Next Learning Topics:
  • React Lists: combine conditional rendering with .map() for empty/filtered states
  • useState: drive these conditions from real component state
  • useEffect: fetch data and manage the loading/error/success states shown here
  • React Hooks Deep Dive: custom hooks for reusable loading/error logic

Keep practicing! 💪 Conditional rendering is just JavaScript — the more comfortable you get with &&, ternaries, and early returns, the more readable every component you write becomes.

About the Author

TG

Thirdy Gayares

Passionate developer creating custom solutions for everyone. I specialize in building user-friendly tools that solve real-world problems while maintaining the highest standards of security and privacy.