# 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.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"react/jsx-no-leaked-render" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"react/jsx-no-leaked-render" = ["error", {
  validStrategies = ["ternary", "coerce"],
}]
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad {"count": 2} */}
```jsx
function Cart({ items, note }) {
  return (
    <Panel footer={note && <Note text={note} />}>
      {items.length && <List items={items} />}
    </Panel>
  );
}
```

Not reported:

{/* good */}
```jsx
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:

{/* bad {"options": [{"validStrategies": ["ternary"]}]} */}
```jsx
const cart = <div>{!!items.length && <List items={items} />}</div>;
```

{/* good {"options": [{"validStrategies": ["ternary"]}]} */}
```jsx
const 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:

{/* bad {"options": [{"validStrategies": ["coerce"]}]} */}
```jsx
const cart = <div>{items.length ? <List items={items} /> : null}</div>;
```

{/* good {"options": [{"validStrategies": ["coerce"]}]} */}
```jsx
const 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.
