Mastering Conditional Rendering in React: Keep Your Code Clean and Readable

Mastering Conditional Rendering in React: Keep Your Code Clean and Readable
Photo by Fili Santillán / Unsplash

Conditional rendering is one of the most common patterns in React. Whether you're toggling a loading spinner, displaying an error message, or hiding/showing parts of your UI, how you handle conditions in JSX directly impacts your code's readability and maintainability.

One of the simplest and cleanest techniques is using logical && operators instead of traditional if statements. Let's explore this approach and other useful tips to level up your React code.

1. Why Use && Instead of if?

In React, embedding if statements inside JSX can become messy, especially as your components grow in complexity. Enter the logical && operator, which makes your code concise and eliminates the need for verbosity.

For example, consider this component:

function MyComponent({ isLoading }) {
  return (
    <div>
      <h1>Welcome to the App!</h1>
      {isLoading && <Spinner />}
    </div>
  );
}

Here’s how it works:

  • If isLoading is truthy, the <Spinner /> component renders.
  • If isLoading is falsy, React simply skips rendering anything for that expression.

This technique keeps your code short and to the point without sacrificing clarity.

2. Handling "Else" Conditions with Ternary Operators

The && operator is excellent for cases where you only need to render something conditionally, but what if you also need to handle an "else" case? Enter the ternary operator, which is equally concise and readable.

Example:

function MyComponent({ isLoading }) {
  return (
    <div>
      {isLoading ? <Spinner /> : <Content />}
    </div>
  );
}

In this scenario:

  • If isLoading is true, <Spinner /> renders.
  • Otherwise, <Content /> renders.

3. Default Fallback with Short-Circuit Evaluation

The logical || operator can provide a default fallback when a variable might be undefined or null.

Example:

function MyComponent({ message }) {
  return <div>{message || "No message available"}</div>;
}

Here, if message is falsy (e.g., null, undefined, or an empty string), the text "No message available" will render instead.

4. Combining Multiple Conditions

For more complex cases, you can chain multiple conditions using logical operators.

Example:

function MyComponent({ isLoading, hasError }) {
  return (
    <div>
      {hasError && <ErrorMessage />}
      {isLoading && <Spinner />}
    </div>
  );
}

This approach makes it clear that different components are conditionally rendered based on their respective flags.

5. Be Wary of Truthy and Falsy Values

React will evaluate any expression inside {} in JSX, so you need to be mindful of what values you pass into conditions. For example:

  • 0, false, undefined, null, NaN, and "" are falsy.
  • Non-empty strings, objects, arrays, and true are truthy.

If you're not careful, unexpected rendering bugs can occur:

function MyComponent({ items }) {
  return <div>{items.length && <p>{items.length} items found</p>}</div>;
}

If items.length is 0, React will render 0 instead of skipping the <p> element. To fix this, explicitly check for truthy conditions:

{items.length > 0 && <p>{items.length} items found</p>}

6. Use Fragments for Cleaner Output

When rendering multiple conditional elements, you can wrap them in React fragments to avoid unnecessary div nesting:

function MyComponent({ isLoading, hasError }) {
  return (
    <>
      {hasError && <ErrorMessage />}
      {isLoading && <Spinner />}
    </>
  );
}

7. Avoid Overcomplicating JSX

While concise logic is great, don’t overuse conditional operators to the point where your JSX becomes unreadable. If you find yourself nesting multiple conditions or repeating the same logic, consider extracting the logic into a separate function.

Example:

function renderContent(isLoading, hasError) {
  if (hasError) return <ErrorMessage />;
  if (isLoading) return <Spinner />;
  return <Content />;
}

function MyComponent({ isLoading, hasError }) {
  return <div>{renderContent(isLoading, hasError)}</div>;
}

8. Remember Performance Implications

React efficiently handles rendering, but unnecessary conditional checks can still add overhead. Use memoization (React.memo, useMemo, or useCallback) when appropriate to optimize rendering of conditional components, especially in lists or large UIs.

Finally

  • Use && for concise rendering when no "else" case is needed.
  • Rely on ternary operators for clean "if-else" conditions.
  • Use || to provide default fallbacks for undefined values.
  • Combine multiple conditions carefully with proper logic.
  • Extract logic into functions if JSX becomes too complex.

By adopting these practices, you’ll keep your React components clean, readable, and maintainable.

Support Us