React Conditional Rendering: Why {count && <X/>} Renders a Stray 0
When count is 0, the expression {count && <Badge/>} evaluates to 0 - and React renders it. React skips false, null, and undefined, but a falsy number like 0 leaks straight onto the page. One character change fixes it.
Why React renders 0
JSX conditional rendering usually looks like this:
{unread && <span>{unread} unread</span>}
When unread is 0, JavaScript short-circuits: the && expression
evaluates to 0 (the left operand), not to false. React renders numbers
directly, so 0 appears on the screen. This is not a React bug - it
behaves exactly as JavaScript says it should. The trap is that 0 is falsy,
so developers expect it to suppress the right side, but React renders any
number it receives, 0 included.
Only these values are skipped by React: false, null, undefined, and an
empty string. 0 and NaN are rendered.
The fix: guard with a real boolean
Replace the falsy number with an explicit boolean test:
// Before - stray 0 when unread is 0
{unread && <span>{unread} unread</span>}
// After - nothing renders when unread is 0
{unread > 0 && <span>{unread} unread</span>}
Two other safe patterns:
// Double-bang coerces any falsy value to false
{!!unread && <span>{unread} unread</span>}
// Ternary returns null explicitly
{unread ? <span>{unread} unread</span> : null}
All three produce false/null when the count is zero, which React skips.
The same bug with arrays
The pattern bites arrays too:
// Renders 0 when items is an empty array
{items.length && <List items={items} />}
// Fixed
{items.length > 0 && <List items={items} />}
Any time the left operand of && is a number (count, length, index), guard
it with a comparison rather than leaning on truthiness.
Lint rules that catch it automatically
The ESLint plugin for React ships a rule that flags this pattern:
"react/jsx-no-leaked-render": ["error", { "validStrategies": ["ternary", "coerce"] }]
Enabling it turns the entire class of stray-number renders into a build-time error, so it never reaches code review.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Spotting falsy-number guards ({count && ...}) and replacing them with explicit boolean tests
- Using {count > 0 && <X/>}, {!!count && <X/>}, or {count ? <X/> : null} safely
- Enabling the react/jsx-no-leaked-render ESLint rule to catch it at build time
FAQ
Why does React render a 0 instead of nothing?
React renders any number it receives, including 0. When you write {count && <X/>} and count is 0, the && expression short-circuits to 0 - a number, not false - so React prints it. Use {count > 0 && <X/>} to guard with a real boolean.
How do I conditionally render a component only when a count is positive?
Use an explicit comparison: {count > 0 && <Badge/>}. You can also use a ternary: {count ? <Badge/> : null}. Both ensure React receives false or null when count is 0, which it skips.
Does the stray 0 bug happen with arrays in React?
Yes - {items.length && <List/>} renders 0 when the array is empty because length is 0, a number. Fix it with {items.length > 0 && <List/>}.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →