DocumentationRulesno-leaked-conditional-rendering

no-leaked-conditional-rendering

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

  • core
  • recommended
  • recommended-typescript
  • recommended-type-checked

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 () {
  return <>{0 && < />}</>;
  //        ^
  //        - Possible unexpected value will be rendered (React Dom: renders undesired '0', React Native: crashes đź’Ą).
}
import React from "react";
 
function () {
  return <>{ && < />}</>;
  //        - Possible unexpected value will be rendered (React Dom: renders undesired 'NaN', React Native: crashes đź’Ą).
}
import React from "react";
 
function Example() {
  return <>{"" && <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 {
  : number;
}
 
function ({  }: ExampleProps) {
  return <>{ && <>There are {} results</>}</>;
  //           - Potential leaked value 'count' that might cause unintentionally rendered values or rendering crashes.
}
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{. && < ={} />}</>;
  //           - Potential leaked value 'items.length' that might cause unintentionally rendered values or rendering crashes.
}
 
declare const : React.<{ : string[] }>;
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{[0] && < ={} />}</>;
  //           - Potential leaked value 'items[0]' that might cause unintentionally rendered values or rendering crashes.
}
 
declare const : React.<{ : string[] }>;
import React from "react";
 
interface ExampleProps {
  : number;
  : number;
}
 
function ({ ,  }: ExampleProps) {
  return (
    <>{( || ) && <>{ + }</>}</>
    //    - Potential leaked value '(numberA || numberB)' that might cause unintentionally rendered values or rendering crashes.
  );
}
 
declare const : React.<React.>;

Passing

import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{}</>;
}
import React from "react";
 
interface ExampleProps {
  : string;
}
 
const  = "Default Title";
 
function ({  }: 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 <>{ || }</>; }
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>There are {.} items</>;
}
import React from "react";
 
interface ExampleProps {
  : string[];
  : number;
}
 
function ({ ,  }: ExampleProps) {
  return <>{! && "No results found"}</>;
}
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{!!. && < ={} />}</>;
}
 
declare const : React.<{ : string[] }>;
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{(.) && < ={} />}</>;
}
 
declare const : React.<{ : string[] }>;
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{. > 0 && < ={} />}</>;
}
 
declare const : React.<{ : string[] }>;
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{. ? < ={} /> : null}</>;
}
 
declare const : React.<{ : string[] }>;
import React from "react";
 
interface ExampleProps {
  : string[];
}
 
function ({  }: ExampleProps) {
  return <>{. ? < ={} /> : < />}</>;
}
 
declare const : React.<{ : string[] }>;
declare const : React.;

Further Reading