Rules
no-leaked-conditional-rendering

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:

import React from "react";
 
function function Example(): React.JSX.ElementExample() {
  return <>{0 && <JSX.IntrinsicElements.view: React.SVGProps<SVGViewElement>view />}</>;
  //        ^
  //        - Possible unexpected value will be rendered (React Dom: renders undesired '0', React Native: crashes 💥).
}
import React from "react";
 
function function Example(): React.JSX.ElementExample() {
  return <>{var NaN: numberNaN && <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div />}</>;
  //        - Possible unexpected value will be rendered (React Dom: renders undesired 'NaN', React Native: crashes 💥).
}
import React from "react";
 
function function Example(): React.JSX.ElementExample() {
  return <>{"" && <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div />}</>;
  //        - Possible unexpected value will be rendered (React Dom: renders nothing, React Native, with React below 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}

Failing

import React from "react";
 
interface ExampleProps {
  ExampleProps.count: numbercount: number;
  ExampleProps.title: stringtitle: string;
}
 
function function Example({ count, title }: ExampleProps): React.JSX.ElementExample({ count: numbercount, title: stringtitle }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{count: numbercount && title: stringtitle}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
  //           - Potential leaked value that might cause unintentionally rendered values or rendering crashes.
}
import React from "react";
 
interface ExampleProps {
  ExampleProps.count: numbercount: number;
}
 
function function Example({ count }: ExampleProps): React.JSX.ElementExample({ count: numbercount }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{count: numbercount && <JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span>There are {count: numbercount} results</JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span>}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
  //           - Potential leaked value that might cause unintentionally rendered values or rendering crashes.
}
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
&& <const List: React.ComponentType<{
items: string[];
}>
List
items: string[]items={items: string[]items} />}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
// - Potential leaked value that might cause unintentionally rendered values or rendering crashes. } declare const const List: React.ComponentType<{
items: string[];
}>
List
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<{ items: string[]items: string[] }>;
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{items: string[]items[0] && <const List: React.ComponentType<{
items: string[];
}>
List
items: string[]items={items: string[]items} />}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
// - Potential leaked value that might cause unintentionally rendered values or rendering crashes. } declare const const List: React.ComponentType<{
items: string[];
}>
List
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<{ items: string[]items: string[] }>;
import React from "react";
 
interface ExampleProps {
  ExampleProps.numberA: numbernumberA: number;
  ExampleProps.numberB: numbernumberB: number;
}
 
function function Example({ numberA, numberB }: ExampleProps): React.JSX.ElementExample({ numberA: numbernumberA, numberB: numbernumberB }: ExampleProps) {
  return (
    <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{(numberA: numbernumberA || numberB: numbernumberB) && <const Results: React.ComponentType<{
children?: React.ReactNode;
}>
Results
>{numberA: numbernumberA + numberB: numbernumberB}</const Results: React.ComponentType<{
children?: React.ReactNode;
}>
Results
>}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>
// - Potential leaked value that might cause unintentionally rendered values or rendering crashes. ); } declare const const Results: React.ComponentType<{
children?: React.ReactNode;
}>
Results
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<React.type React.PropsWithChildren<P = unknown> = P & {
children?: React.ReactNode;
}
PropsWithChildren
>;

Passing

import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{items: string[]items}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
}
import React from "react";
 
interface ExampleProps {
  ExampleProps.customTitle: stringcustomTitle: string;
}
 
const const defaultTitle: "Default Title"defaultTitle = "Default Title";
 
function function Example({ customTitle }: ExampleProps): React.JSX.ElementExample({ customTitle: stringcustomTitle }: ExampleProps) {
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
return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{customTitle: stringcustomTitle || const defaultTitle: "Default Title"defaultTitle}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>; }
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>There are {items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
} items</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
}
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
  ExampleProps.count: numbercount: number;
}
 
function function Example({ items, count }: ExampleProps): React.JSX.ElementExample({ items: string[]items, count: numbercount }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{!count: numbercount && "No results found"}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
}
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{!!items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
&& <const List: React.ComponentType<{
items: string[];
}>
List
items: string[]items={items: string[]items} />}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
} declare const const List: React.ComponentType<{
items: string[];
}>
List
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<{ items: string[]items: string[] }>;
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{var Boolean: BooleanConstructor
<number>(value?: number | undefined) => boolean
Boolean
(items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) && <const List: React.ComponentType<{
items: string[];
}>
List
items: string[]items={items: string[]items} />}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
} declare const const List: React.ComponentType<{
items: string[];
}>
List
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<{ items: string[]items: string[] }>;
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0 && <const List: React.ComponentType<{
items: string[];
}>
List
items: string[]items={items: string[]items} />}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
} declare const const List: React.ComponentType<{
items: string[];
}>
List
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<{ items: string[]items: string[] }>;
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
? <const List: React.ComponentType<{
items: string[];
}>
List
items: string[]items={items: string[]items} /> : null}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
} declare const const List: React.ComponentType<{
items: string[];
}>
List
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<{ items: string[]items: string[] }>;
import React from "react";
 
interface ExampleProps {
  ExampleProps.items: string[]items: string[];
}
 
function function Example({ items }: ExampleProps): React.JSX.ElementExample({ items: string[]items }: ExampleProps) {
  return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>{items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
? <const List: React.ComponentType<{
items: string[];
}>
List
items: string[]items={items: string[]items} /> : <const EmptyList: React.ComponentType<{}>EmptyList />}</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>;
} declare const const List: React.ComponentType<{
items: string[];
}>
List
: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
<{ items: string[]items: string[] }>;
declare const const EmptyList: React.ComponentType<{}>EmptyList: React.type React.ComponentType<P = {}> = React.ComponentClass<P, any> | React.FunctionComponent<P>
Represents any user-defined component, either as a function or a class. Similar to {@link JSXElementConstructor } , but with extra properties like {@link FunctionComponent.defaultProps defaultProps } and {@link ComponentClass.contextTypes contextTypes } .
@templateP The props the component accepts.@see{@link ComponentClass}@see{@link FunctionComponent}
ComponentType
;

Further Reading