Three Patterns for "Render This Sometimes"
Conditional Rendering
Three idiomatic ways to render different things based on a condition — early return, `&&`, and ternary.
What you'll learn
- Use early return for distinct page-level shapes
- Use `&&` to show or hide a single element
- Use ternaries for "this or that"
UIs constantly switch on state — logged in vs out, loading vs
loaded, expanded vs collapsed. JSX has no if inside { }, but
you’ve got three idiomatic patterns.
1. Early Return
Best when the component renders something completely different in one branch.
function Profile({ user }) {
if (!user) return <Login />;
return (
<div>
<h1>{user.name}</h1>
<p>{user.bio}</p>
</div>
);
} Or just return null to render nothing:
function Banner({ show, message }) {
if (!show) return null;
return <div className="banner">{message}</div>;
} 2. && — Show Or Don’t
Best when ONE element should appear when a condition holds.
function Inbox({ count }) {
return (
<div>
<h1>Inbox</h1>
{count > 0 && <span className="badge">{count}</span>}
</div>
);
} 3. Ternary — This Or That
Best when you have exactly two options.
function Status({ online }) {
return (
<span className={online ? "on" : "off"}>
{online ? "Online" : "Offline"}
</span>
);
} For larger branches, ternaries get unreadable fast. If both branches are non-trivial, switch to early return or extract sub-components.
Picking Between Patterns
| Situation | Best pattern |
|---|---|
| Whole component is different | Early return |
| One element appears or doesn’t | cond && <X/> |
| Two clear alternatives | Ternary |
| More than two alternatives | Helper function or object lookup |
Many Branches → Object Lookup
For 3+ states, an object map reads better than nested ternaries:
function StatusIcon({ status }) {
const icons = {
ok: <CheckIcon />,
error: <XIcon />,
warning: <AlertIcon />,
pending: <SpinnerIcon />,
};
return icons[status] ?? null;
} Extracting Helpers
When a render has too many branches inline, hide them in functions:
function renderBody(state) {
if (state.loading) return <Spinner />;
if (state.error) return <Error message={state.error} />;
if (!state.data) return <Empty />;
return <Results data={state.data} />;
}
function Page({ state }) {
return <div className="page">{renderBody(state)}</div>;
} Same idea, much easier to scan.
Up Next
The other half of dynamic UI — rendering lists.
Rendering Lists →