When to Avoid Conditional Rendering in React
Conditional rendering is a core pattern in React that allows you to display UI elements based on specific state or props. However, while highly useful, there are several scenarios where conditional rendering can introduce UI bugs, hurt performance, or ruin code readability. This article highlights the key situations when you should avoid conditional rendering in React and offers cleaner, more robust alternatives.
1. Using the
&& Operator with Falsy Values
The short-circuit && operator is a popular way
to render components conditionally. However, you should avoid it when
dealing with variables that can resolve to falsy values like
0 or NaN.
In JavaScript, if the left side of an &&
expression evaluates to 0, React will render the
0 directly to the DOM instead of rendering nothing.
// Avoid this: If items.length is 0, it renders "0" on the screen
const List = ({ items }) => {
return <div>{items.length && <ItemRepeater items={items} />}</div>;
};The Alternative: Use a ternary operator or cast the value to a boolean.
// Better: Use a ternary operator
{items.length > 0 ? <ItemRepeater items={items} /> : null}
// Better: Double negation to force a boolean
{!!items.length && <ItemRepeater items={items} />}2. Complex Nested Ternaries in JSX
When you have multiple conditions that dictate what to render, nesting ternary operators inside your return statement makes the JSX incredibly difficult to read, debug, and maintain.
// Avoid this
return (
<div>
{isLoading ? <Spinner /> : isError ? <Error /> : data ? <DataView /> : <Empty />}
</div>
);The Alternative: Extract the conditional logic into helper functions, separate sub-components, or use early returns before the main render statement.
// Better: Early returns
if (isLoading) return <Spinner />;
if (isError) return <Error />;
if (!data) return <Empty />;
return <DataView data={data} />;3. Frequent Toggling of Heavy Components (Performance Issues)
When you conditionally render a component (e.g.,
showComponent && <ExpensiveComponent />),
React completely mounts or unmounts that component from the DOM. If the
component contains complex layouts, heavy logic, or large lists,
repeatedly mounting and unmounting it during frequent toggles can cause
noticeable UI lag.
Additionally, unmounting a component destroys its local state. If you need to preserve the user’s input or scroll position, conditional rendering will wipe that data.
The Alternative: Keep the component mounted but hide
it visually using CSS display: none or visibility
classes.
// Better: Component stays mounted, preserving state and avoiding remounting lag
<div style={{ display: isVisible ? 'block' : 'none' }}>
<ExpensiveComponent />
</div>4. Components Requiring Exit Animations
If you rely on React’s conditional rendering to remove a component from the DOM instantly, any CSS exit transitions or animations applied to that component will not play. The element disappears immediately before the animation can execute.
The Alternative: Use animation libraries designed
for React, such as Framer Motion (with
<AnimatePresence>) or React Transition Group.
Alternatively, manage the open/closed state using CSS classes that
handle the scale, opacity, and removal after the transition ends.
// Better: Let the animation library handle the unmounting after the exit animation plays
<AnimatePresence>
{isOpen && (
<motion.div initial={{ opacity: 0 }} exit={{ opacity: 0 }}>
<Modal />
</motion.div>
)}
</AnimatePresence>