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
ifwith early return for whole branches; returnnullto render nothing - Use
cond ? a : bfor either/or andcond && xfor show/hide - Keep the left side of
&&boolean:count > 0 && ..., notcount && ...
Watch out for
{items.length && <List />}renders a stray 0 when the array is empty.