Conditional rendering in React means showing different UI based on state or props. Common patterns include && for simple toggles, ternaries for two branches, and early returns for guards. This keeps rendering logic explicit and makes components easier to read. Conditional UI affects accessibility and layout stability. Test empty states, transitions, and focus behavior.
Conditional rendering in React: patterns, trade-offs, and gotchas
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Core idea
Conditional rendering in React is just JavaScript: your component returns different ReactNode values depending on conditions (state/props/context). React renders whatever you return. Returning null (or false) means “render nothing”.
Pattern | What you write | Best when |
|---|---|---|
Guard clause (early return) |
| One branch is a clear gate (loading/auth/empty/error) |
Inline ternary |
| Two short alternatives in JSX |
Render-only-when-true (&&) |
| You only need the “true” branch (else = nothing) |
Switch / mapping |
| Multiple states (idle/loading/error/success) |
Extract to variable/function |
| JSX gets messy; want readability + testability |
// 1) Guard clause (early return)
function UserView({ user, isLoading, error }) {
if (isLoading) return <Spinner />;
if (error) return <ErrorBanner message={error.message} />;
if (!user) return null; // render nothing
return <Profile user={user} />;
}
// 2) Inline ternary
function Greeting({ isLoggedIn }) {
return (
<h1>
{isLoggedIn ? 'Welcome back!' : 'Please sign in.'}
</h1>
);
}
// 3) Logical AND (render only when true)
function Notifications({ messages }) {
const count = messages.length;
return (
<>
{count > 0 && <p>You have {count} new messages.</p>}
</>
);
}
// 4) Switch / mapping (multiple UI states)
function Page({ status }) {
const views = {
idle: <p>Ready</p>,
loading: <Spinner />,
error: <ErrorBanner message="Something failed" />,
success: <DataView />
};
return views[status] ?? <p>Unknown status</p>;
}
Common gotchas
Most bugs come from (1) non-boolean values with &&, (2) returning undefined by accident, or (3) unreadable nested conditions.
Gotcha | What happens | Fix |
|---|---|---|
| Renders | Use |
Arrow function with braces but no return | Component returns | Use |
Nested ternaries | Hard to read/debug; easy to mis-handle edge cases | Extract to variable/function or use a mapping |
Inline objects/functions used as conditions/props | Identity changes can cause extra renders, not a rendering bug but a perf trap | Stabilize only where it matters ( |
Mounting matters: preserve vs reset component state
Conditional rendering often means mount/unmount. Unmounting resets local state. If you need to preserve internal state, keep the component mounted and hide it instead.
// Unmounts when closed (state resets on reopen)
function App({ open }) {
return open ? <Modal /> : null;
}
// Keeps mounted (state preserved), just hidden
function AppPreserve({ open }) {
return <Modal style={{ display: open ? 'block' : 'none' }} />;
}
// Forcing a reset on purpose: change the key
function ProfileEditor({ userId }) {
return <Editor key={userId} userId={userId} />;
}
Rule of thumb | Why |
|---|---|
Use guard clauses for gating (loading/error/auth/empty) | Keeps JSX clean and makes branches obvious |
Use ternary when you truly have two alternatives | Makes the “else” explicit (vs implicit nothing) |
Use | Avoid rendering |
For 3+ states, use a mapping/switch | Scales better than nested ternaries |
Be intentional about mount/unmount | Unmount resets local state; hiding preserves it |
Practical scenario
Show a loading spinner until data arrives, then replace it with content.
Common pitfalls
- Layout jump when components mount/unmount.
- Focus loss when elements are removed.
- Rendering heavy components unnecessarily.
Conditional render is simple but can cause UX shifts. Test loading transitions and focus retention.
Conditional rendering is simply returning different ReactNode outputs based on conditions. Choose a pattern by complexity: guard clauses for gating, ternaries for two options, and mappings/switches for multiple states. Be careful with && when the condition might be a non-boolean (especially 0). Finally, remember that mount/unmount controls whether local component state is preserved or reset (and key can force a reset when needed).