Try @eslint-react/kit@beta
logoESLint React

no-leaked-conditional-rendering

Prevents problematic leaked values from being rendered.

Full Name in eslint-plugin-react-x

react-x/no-leaked-conditional-rendering

Full Name in @eslint-react/eslint-plugin

@eslint-react/no-leaked-conditional-rendering

Features

💭

Presets

recommended-type-checked strict-type-checked

Rule Details

Using the && operator to render an element conditionally in JSX can cause unexpected values to be rendered or even crash the rendering.

Examples

Using a number directly as a condition

// Problem: When count is 0, 0 will be rendered directly on the page
interface MyComponentProps {
  count: number;
}

function MyComponent({ count }: MyComponentProps) {
  return <div>{count && <span>There are {count} results</span>}</div>;
  //           ^^^ Potential leaked value 'count' that might cause unintentionally rendered values or rendering crashes.
}
// Recommended: Use a comparison expression or ternary operator to ensure only boolean evaluation results are rendered
interface MyComponentProps {
  count: number;
}

function MyComponent({ count }: MyComponentProps) {
  return <div>{count > 0 && <span>There are {count} results</span>}</div>;
}

Using array length as a condition

// Problem: When items.length is 0, 0 may leak into the DOM
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{items.length && <List items={items} />}</div>;
  //           ^^^ Potential leaked value 'items.length' that might cause unintentionally rendered values or rendering crashes.
}
// Recommended: Use !!, Boolean(), or a comparison expression to avoid leaking
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{!!items.length && <List items={items} />}</div>;
}
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{Boolean(items.length) && <List items={items} />}</div>;
}
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{items.length > 0 && <List items={items} />}</div>;
}
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{items.length ? <List items={items} /> : null}</div>;
}
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{items.length ? <List items={items} /> : <EmptyList />}</div>;
}

Using an array element as a condition

// Problem: When items\[0] is an empty string or 0, that value may be rendered unexpectedly
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{items[0] && <List items={items} />}</div>;
  //           ^^^ Potential leaked value 'items[0]' that might cause unintentionally rendered values or rendering crashes.
}

Using a logical OR expression as a condition

// Problem: (numberA || numberB) may return 0 or another falsy value and leak onto the page
interface MyComponentProps {
  numberA: number;
  numberB: number;
}

function MyComponent({ numberA, numberB }: MyComponentProps) {
  return (
    <div>{(numberA || numberB) && <Results>{numberA + numberB}</Results>}</div>
    //    ^^^ Potential leaked value '(numberA || numberB)' that might cause unintentionally rendered values or rendering crashes.
  );
}

Using negation for conditional rendering

// OK: When the condition expression explicitly produces a boolean result, no value will leak
interface MyComponentProps {
  items: string[];
  count: number;
}

function MyComponent({ items, count }: MyComponentProps) {
  return <div>{!count && "No results found"}</div>;
}

Rendering arrays or strings directly

// OK: Directly rendering values known to be React nodes does not require conditional checks
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>{items}</div>;
}
interface MyComponentProps {
  items: string[];
}

function MyComponent({ items }: MyComponentProps) {
  return <div>There are {items.length} items</div>;
}

Using a default value fallback

// OK: Using `||` to provide a fallback value is a common default-value pattern, not conditional rendering
interface MyComponentProps {
  customTitle: string;
}

const defaultTitle = "Default Title";

function MyComponent({ customTitle }: MyComponentProps) {
  return <div>{customTitle || defaultTitle}</div>;
}

Versions

Resources

Further Reading

On this page