react/jsx-no-leaked-render
Disallow && conditions in JSX that can render 0 or NaN
{count && <List />} evaluates to count when count is falsy. React renders nothing for false, null and undefined, but it does render 0 and NaN, so an empty list shows a stray 0 on the page. In React Native, a number or a string outside <Text> crashes the app.
The rule reports && in JSX braces, in children and in props, unless its left side looks like a boolean: !x or !!x, a comparison, any call such as Boolean(count), or a variable declared as true or false.
--fix rewrites the condition with the first allowed strategy.
Configure#
Off by default. To turn it on:
[lint.rules]
"react/jsx-no-leaked-render" = "error" # or "warn"Every option, set to its default:
[lint.rules]
"react/jsx-no-leaked-render" = ["error", {
validStrategies = ["ternary", "coerce"],
}]Examples#
function Cart({ items, note }) {
return (
<Panel footer={note && <Note text={note} />Potential leaked value that might cause unintentionally rendered values or rendering crashes}>
{items.length && <List items={items} />Potential leaked value that might cause unintentionally rendered values or rendering crashes}
</Panel>
);
}function Cart({ items }) {
return (
<div>
{items.length > 0 && <List items={items} />}
{!!items.length && <Total items={items} />}
{Boolean(items.length) && <Coupon />}
{items.length ? <Checkout /> : null}
</div>
);
}Options#
| Option | Default | What it does |
|---|---|---|
validStrategies | ["ternary", "coerce"] | The allowed ways to write a condition. "ternary" is test ? <A /> : null. "coerce" is && with a boolean on the left. |
With only "ternary", every && is reported:
{ "validStrategies": ["ternary"] }1 problemconst cart = <div>{!!items.length && <List items={items} />Potential leaked value that might cause unintentionally rendered values or rendering crashes}</div>;{ "validStrategies": ["ternary"] }No problemsconst cart = <div>{items.length ? <List items={items} /> : null}</div>;With only "coerce", a ternary is reported too, unless it ends in another element or in a value such as a string:
{ "validStrategies": ["coerce"] }1 problemconst cart = <div>{items.length ? <List items={items} /> : nullPotential leaked value that might cause unintentionally rendered values or rendering crashes}</div>;{ "validStrategies": ["coerce"] }No problemsconst cart = <div>{items.length > 0 && <List items={items} />}</div>;
const list = <div>{items.length ? <List items={items} /> : <Empty />}</div>;
const count = <div>{items.length ? items.length : "none"}</div>;When not to use it#
The rule doesn't use types. So it also reports {user && <Profile user={user} />}, even when user is an object or undefined and nothing can leak.