React · State & Events

Conditional Rendering

UIs change with data: show a spinner while loading, an error if something failed, a “Sold out” badge when stock is zero. React uses plain JavaScript to decide what to render.

Beginner 5 min Lesson 10 of 42Examples target React 19 with Vite.
Before you start:Props
0/42 in React
On this page · 5 min · Beginner

Learning objectives#

  • Choose between elements with if, ternary and &&
  • Return null to render nothing
  • Avoid the “0 on screen” bug with &&
  • Keep complex conditions readable

Explanation#

Before return, use normal if statements and early returns: if (loading) return <Spinner />;.

Inside JSX, choose between two options with a ternary: {isOpen ? <Menu /> : <MenuButton />}.

Show something or nothing with &&: {error && <p>{error}</p>}.

Watch out: {count && <Badge />} renders 0 when count is 0, because 0 is falsy but still rendered. Use {count > 0 && <Badge />}.

Returning null from a component renders nothing. For many cases, a variable set before return or an object lookup ({ success: <Ok />, error: <Fail /> }[status]) keeps JSX readable.

Syntax#

JSX Illustrative
if (loading) return <p>Loading…</p>;
return (
  <>
    {user ? <p>Hi {user.name}</p> : <button>Log in</button>}
    {items.length > 0 && <Cart items={items} />}
  </>
);

Code example: Order status in four states#

JSXOrderStatus.jsx Runnable
function StockBadge({ stock }) {
  if (stock > 10) return null;                             // nothing to show
  return <span>{stock === 0 ? 'Sold out' : `Only ${stock} left`}</span>;
}


function OrderStatus({ status, order, error }) {
  if (status === 'loading') return <p>Loading order…</p>;    // early return
  if (status === 'error') return <p role="alert">Error: {error}</p>;


  return (
    <article>
      <h3>Order #{order.id}</h3>
      {order.items.length > 0 && <p>{order.items.length} items</p>}
      {order.items.length === 0 && <p>No items</p>}
      {order.delivered ? <p>Delivered ✓</p> : <p>On the way 🚚</p>}
      <StockBadge stock={order.stock} />
    </article>
  );
}


export default function Demo() {
  return (
    <>
      <OrderStatus status="loading" />
      <OrderStatus status="error" error="Network down" />
      <OrderStatus status="ok" order={{ id: 7, items: [], delivered: false, stock: 0 }} />
      <OrderStatus status="ok" order={{ id: 8, items: ['Pen', 'Bag'], delivered: true, stock: 40 }} />
    </>
  );
}
Expected output
Loading order…
Error: Network down
Order #7 — No items — On the way 🚚 — Sold out
Order #8 — 2 items — Delivered ✓       (no stock badge: stock is 40)

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. Early returns handle loading and error before any order data is read.
  2. items.length > 0 && ... avoids printing a stray 0 for empty orders.
  3. A ternary switches between “Delivered” and “On the way”.
  4. StockBadge returns null when stock is high, so nothing is rendered.

Real-world use case#

Every data screen has the same shape: if loading show a skeleton, if error show a retry button, if empty show “No orders yet”, otherwise show the table.

Common mistakes#

Rendering 0 with &&

{items.length && <List />} shows “0” for an empty list. Compare explicitly: items.length > 0 && ...

Nested ternaries

a ? b : c ? d : e is hard to read. Use early returns or a lookup object.

Reading data before checking it exists

order.items.length crashes while order is undefined. Handle loading first.

Best practices#

  • Early returns for loading/error/empty
  • Ternary for either-or, && for show-or-nothing
  • Explicit boolean conditions with &&
  • Return null to hide a component

Remember this#

Either/or → ternary. Maybe → &&. Nothing → null.

{count > 0 && …}, never {count && …}.

Handle loading and error first.

Practice exercise#

Your task: Write a Greeting component: if user is null show a "Log in" button; if user.isAdmin show "Welcome back, admin <name>"; otherwise "Welcome back, <name>".

Need a hint?
Early return for null, then a ternary for the admin check.
Show solution
JSX Runnable
export default function Greeting({ user = { name: 'Asha', isAdmin: true } }) {
  if (!user) return <button>Log in</button>;
  return <p>Welcome back, {user.isAdmin ? `admin ${user.name}` : user.name}</p>;
}

Mini quiz#

Conditional Rendering quizPredict the output Question 1 of 3

messages is an empty array. What appears on screen?

<div>{messages.length && <Inbox />}</div>
Score so far: 0/0

Want more? Practise all React MCQs · React interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.