Conditional rendering in React: patterns, trade-offs, and gotchas

LowIntermediateReact
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

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.

Answer

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)

if (cond) return A; return B;

One branch is a clear gate (loading/auth/empty/error)

Inline ternary

{cond ? A : B}

Two short alternatives in JSX

Render-only-when-true (&&)

{cond && A}

You only need the “true” branch (else = nothing)

Switch / mapping

views[state] ?? fallback

Multiple states (idle/loading/error/success)

Extract to variable/function

const content = ...

JSX gets messy; want readability + testability

Common conditional rendering patterns
JSX
// 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} />;
}
                  
JSX
// 2) Inline ternary
function Greeting({ isLoggedIn }) {
  return (
    <h1>
      {isLoggedIn ? 'Welcome back!' : 'Please sign in.'}
    </h1>
  );
}
                  
JSX
// 3) Logical AND (render only when true)
function Notifications({ messages }) {
  const count = messages.length;

  return (
    <>
      {count > 0 && <p>You have {count} new messages.</p>}
    </>
  );
}
                  
JSX
// 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

{count && <Badge />} with count = 0

Renders 0 as text (because 0 is renderable)

Use count > 0 ? <Badge /> : null

Arrow function with braces but no return

Component returns undefined → “Nothing was returned from render”

Use () => ( ... ) or add return

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 (memo boundaries)

Typical conditional rendering pitfalls

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.

JSX
// 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' }} />;
}
                  
JSX
// 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 && only with boolean conditions

Avoid rendering 0 / empty strings accidentally

For 3+ states, use a mapping/switch

Scales better than nested ternaries

Be intentional about mount/unmount

Unmount resets local state; hiding preserves it

Best practices that interviewers expect

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.
Trade-off or test tip
Conditional render is simple but can cause UX shifts. Test loading transitions and focus retention.

Summary

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).

Similar questions
Guides
23 / 41