Conditional rendering

React · Essentials · 8 min

Almost every component has states like loading, empty or error that render differently.

Because JSX is JavaScript, conditional UI uses ordinary JavaScript. There are three common patterns.

Early return with `if` when a whole branch differs:

if (!user) return <LoginPrompt />;
return <Dashboard user={user} />;

Returning null renders nothing, which is how a component hides itself.

The ternary cond ? a : b inside JSX for small either/or choices: {isPacked ? <s>{name}</s> : name}.

Logical AND cond && <Thing /> when there is no else branch. If the condition is false, React renders nothing.

The classic gotcha with &&: if the left side is the number 0, the expression evaluates to 0, and React renders a literal 0. {messages.length && <Badge />} shows "0" when the list is empty. Make the left side a real boolean: {messages.length > 0 && <Badge />}.

You can also put JSX in a variable and assign it conditionally before the return, which keeps complicated logic out of the markup:

let content = <Spinner />;
if (error) content = <ErrorMessage error={error} />;
else if (data) content = <Results data={data} />;

When the nested ternaries start to pile up, that variable pattern, or extracting a small component, is the readable fix.

Example

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {isPacked ? <del>{name}</del> : name}
      {isPacked && " (packed)"}
    </li>
  );
}

function Inbox({ messages }) {
  if (messages === null) return <p>Loading...</p>;

  return (
    <div>
      {/* messages.length && ... would render "0" for an empty list */}
      {messages.length > 0 && <span className="badge">{messages.length}</span>}
      {messages.length === 0 ? <p>No messages</p> : <p>You have mail</p>}
    </div>
  );
}

export default function App() {
  return (
    <>
      <ul>
        <Item name="Space suit" isPacked={true} />
        <Item name="Helmet" isPacked={false} />
      </ul>
      <Inbox messages={[]} />
    </>
  );
}

Remember

  • Use if with early return for whole branches; return null to render nothing
  • Use cond ? a : b for either/or and cond && x for show/hide
  • Keep the left side of && boolean: count > 0 && ..., not count && ...

Watch out for

  • {items.length && <List />} renders a stray 0 when the array is empty.

Check yourself

  1. What does {count && <p>Items</p>} render when count is 0?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: react.dev/learn/conditional-rendering