How to Conditionally Render an Element or Text in React

Beginner8 min interview
Skills tested:
Using ternary operators for rendering one element or anotherUsing logical AND (&&) for rendering when a condition is trueReturning null from a component to render nothingUsing if/else before the return statement for complex branchingKnowing the falsy 0 gotcha with && and how to avoid it

Advertisement

🧩 Scenario

Conditional rendering is in every React component. Loading spinners, empty states, error messages, admin-only UI, authenticated content, and feature flags all require showing or hiding elements based on conditions. React offers four distinct patterns for this, each with a different readability profile and specific gotchas.

Architecture Walkthrough

The Four Conditional Rendering Patterns

React renders JSX expressions and JavaScript expressions inside curly braces. Conditional rendering is just JavaScript control flow applied to JSX values. There are four patterns, and choosing the right one depends on how many branches there are and how complex each branch is.

The ternary operator is the most versatile: it handles both the true and false cases inline inside JSX and is readable for two-branch conditions of moderate complexity. Logical AND is a shorthand for "render this or nothing"; it only handles the true branch and has a critical falsy-number gotcha. If/else before the return statement is the right tool for three or more branches or when each branch has complex logic. Returning null from a component is how to render nothing cleanly without a DOM placeholder.

The Falsy 0 Bug

The && operator returns the left side if it is falsy, or the right side if the left side is truthy. React renders most falsy values as nothing, but 0 and NaN are rendered as text. {items.length && <List />} renders 0 in the DOM when items is empty. The fix is to ensure the left side is a boolean: {items.length > 0 && <List />} or {Boolean(items.length) && <List />}.

null vs CSS Visibility

Returning null from a component means the component contributes nothing to the DOM. This is different from hiding with CSS: a hidden component is still mounted (its effects run, its subscriptions are active, its children are rendered). Return null when the component should genuinely not exist in the current state; use CSS visibility when you want to keep the component alive but not visible.


Key Code Explained

// Pattern 1: Ternary — two-branch conditions
function AuthButton({ isLoggedIn }: { isLoggedIn: boolean }) {
  return (
    <button>
      {isLoggedIn ? 'Sign Out' : 'Sign In'}
    </button>
  );
}

// Ternary with full element branches
function Content({ isLoading, data }: { isLoading: boolean; data: string | null }) {
  return (
    <div>
      {isLoading
        ? <Skeleton />              // show skeleton while loading
        : <p>{data}</p>            // show content when ready
      }
    </div>
  );
}


// Pattern 2: Logical AND — "show if true, show nothing if false"
function Notification({ count }: { count: number }) {
  return (
    <div>
      <Bell />
      {/* WRONG: renders "0" when count is 0 */}
      {count && <Badge>{count}</Badge>}

      {/* CORRECT: boolean ensures 0 is not rendered */}
      {count > 0 && <Badge>{count}</Badge>}
    </div>
  );
}

// && for optional UI sections
function UserProfile({ user }: { user: User }) {
  return (
    <div>
      <h2>{user.name}</h2>
      {user.bio && <p className="bio">{user.bio}</p>}  {/* only shown if bio exists */}
      {user.isAdmin && <AdminBadge />}                 {/* only shown for admins */}
    </div>
  );
}


// Pattern 3: if/else before return — three or more branches
function FetchStatus({ status }: { status: 'idle' | 'loading' | 'error' | 'success'; data?: string }) {
  // Complex branching is cleaner before return than as nested ternaries in JSX
  if (status === 'loading') {
    return <Spinner />;
  }
  if (status === 'error') {
    return <ErrorMessage message="Something went wrong." />;
  }
  if (status === 'idle') {
    return null; // render nothing in idle state
  }
  return <p>{data}</p>;
}


// Pattern 4: return null — render nothing
function ErrorBanner({ error }: { error: string | null }) {
  if (!error) return null; // contributes nothing to the DOM

  return (
    <div className="error-banner" role="alert">
      {error}
    </div>
  );
}

// Composing patterns in a real component
function ItemList({ items, isLoading, error }: {
  items: string[];
  isLoading: boolean;
  error: string | null;
}) {
  if (isLoading) return <Skeleton />;
  if (error) return <ErrorBanner error={error} />;

  return (
    <ul>
      {items.length > 0
        ? items.map((item) => <li key={item}>{item}</li>)
        : <li className="empty">No items found.</li>
      }
    </ul>
  );
}

The ItemList example shows the correct composition: if/else before return handles the loading and error branches (clean, no nesting), and a ternary inside the return handles the empty vs non-empty list states. This keeps the JSX readable with no deeply nested ternaries.


Tradeoffs

PatternBest forAvoid when
TernaryTwo-branch conditions inline in JSXThree or more branches (nesting gets messy)
Logical AND (&&)"Render if true, nothing if false"Left side can be a falsy number or NaN
if/else before returnThree or more branches, complex per-branch logicSimple one-liners (too verbose)
return nullComponent should not exist in the DOM at allComponent needs to stay mounted (effects, subscriptions)

What Interviewers Actually Check

  • Whether you know all four patterns and can choose the right one for the situation
  • Whether you know the falsy 0 bug with && and how to fix it
  • Whether you know that returning null is the correct way to render nothing
  • Whether you avoid deeply nested ternaries in JSX
  • Whether you know the difference between CSS visibility and conditional rendering via null

Follow-Up Questions

  1. How does optional chaining interact with conditional rendering: {user?.profile?.bio && <Bio text={user.profile.bio} />} — what are the risks?
  2. How would you implement a feature flag system where components check a flag object before rendering?
  3. What is the <Show> pattern from SolidJS and does React have an equivalent?
  4. How would you conditionally render an element only on the server side in Next.js App Router?
  5. How does React.lazy and Suspense relate to conditional rendering for code-split components?

Common Candidate Mistakes

  • Using {count && <Badge />} without knowing it renders 0 in the DOM when count is 0
  • Nesting multiple ternaries inside JSX for three-branch conditions when if/else before return is cleaner
  • Not knowing that returning null from a component is valid and renders nothing
  • Toggling elements with display: none when the component should not be mounted at all
  • Using || for conditional rendering and being confused why the right side renders when the left is any falsy value, not just undefined

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you use ternary to switch between two elements based on a condition?
  • Can you use && to render an element only when a condition is true, and fix the falsy 0 bug?
  • Can you use if/else before return for three or more branches?
  • Can you return null to render nothing from a component?
  • Can you explain when to use CSS visibility vs conditional rendering via null?

Summary

Conditional rendering in React is JavaScript control flow applied to JSX. React evaluates JSX as expressions, so any JavaScript pattern that produces a value can control what renders. The four patterns cover all cases: ternary for two-branch inline conditions, && for "render if true or nothing," if/else before return for complex multi-branch logic, and returning null for "this component contributes nothing right now."

The most important gotcha is the falsy 0 bug: {count && <Badge />} renders the number 0 in the DOM when count is 0 because && returns the left operand when it is falsy, and React renders numbers. Fix it by converting to a boolean: {count > 0 && <Badge />}. The same bug applies to NaN.

Returning null from a component is the correct way to render nothing. It removes the component's output from the DOM entirely, unlike CSS visibility or display: none, which keep the component mounted with its effects and subscriptions running. Use null when the component should not exist; use CSS when the component must stay alive but be invisible.

Frequently Asked Questions

What is the risk of using && for conditional rendering in React?

When the left side is a falsy number like 0, React renders 0 in the DOM instead of nothing. Always convert the condition to a boolean: {count > 0 && <Component />} or {Boolean(count) && <Component />}.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement