jsx/no-leaked-conditional-rendering
💭 This rule requires type information.
Rule category
Suspicious.
What it does
Prevents problematic leaked values from being rendered.
Why is this bad?
Using the && operator to render some element conditionally in JSX can cause unexpected values being rendered, or even crashing the rendering.
Examples
In React, you might end up rendering unexpected values like 0 or NaN. In React Native, your render method will even crash if you render these values:
function Component() {
return (
<>
{0 && <Something />}
{/* React: renders undesired 0 */}
{/* React Native: crashes 💥 */}
{NaN && <Something />}
{/* React: renders undesired NaN */}
{/* React Native: crashes 💥 */}
{"" && <Something />}
{/* React: renders nothing */}
{/* React Native, with React < 18: crashes 💥 */}
</>
);
}
This can be avoided by:
- coercing the conditional to a boolean: {!!someValue && <Something />}
- transforming the binary expression into a ternary expression which returns null for falsy values: {someValue ? <Something /> : null}
❌ Incorrect
function Component({ count, title }) {
return <div>{count && title}</div>;
}
function Component({ count }) {
return <div>{count && <span>There are {count} results</span>}</div>;
}
function Component({ elements }) {
return <div>{elements.length && <List elements={elements} />}</div>;
}
function Component({ nestedCollection }) {
return (
<div>
{nestedCollection.elements.length && <List elements={nestedCollection.elements} />}
</div>
);
}
function Component({ elements }) {
return <div>{elements[0] && <List elements={elements} />}</div>;
}
function Component({ numberA, numberB }) {
return <div>{(numberA || numberB) && <Results>{numberA + numberB}</Results>}</div>;
}
// If the condition is a boolean value, this rule will report the logical expression
// since it can't infer the type of the condition.
function Component({ someBool }) {
return <div>{someBool && <Results>{numberA + numberB}</Results>}</div>;
}
✅ Correct
function Component({ elements }) {
return <div>{elements}</div>;
}
// An OR condition it's considered valid since it's assumed as a way
// to render some fallback if the first value is falsy, not to render something conditionally.
function Component({ customTitle }) {
return <div>{customTitle || defaultTitle}</div>;
}
function Component({ elements }) {
return <div>There are {elements.length} elements</div>;
}
function Component({ elements, count }) {
return <div>{!count && "No results found"}</div>;
}
function Component({ elements }) {
return <div>{!!elements.length && <List elements={elements} />}</div>;
}
function Component({ elements }) {
return <div>{Boolean(elements.length) && <List elements={elements} />}</div>;
}
function Component({ elements }) {
return <div>{elements.length > 0 && <List elements={elements} />}</div>;
}
function Component({ elements }) {
return <div>{elements.length ? <List elements={elements} /> : null}</div>;
}
function Component({ elements }) {
return <div>{elements.length ? <List elements={elements} /> : <EmptyList />}</div>;
}
When Not To Use It
If you are working in a typed-codebase which encourages you to always use boolean conditions, this rule can be disabled.