Skip to content

Latest commit

 

History

History
189 lines (149 loc) · 5.33 KB

jsx-no-leaked-zero.md

File metadata and controls

189 lines (149 loc) · 5.33 KB

Prevent zero from being rendered on numerical condition (react/jsx-no-leaked-zero)

When rendering an element in JSX based on a numerical condition, it might be possible to end up rendering a 0 to the DOM.

The number 0 is a special case for JSX inline conditions, since it's the only falsy expression that it's returned by the render method.

Rule Details

This rule aims to prevent potential numerical condition from rendering a 0 value to the DOM. Since the rule doesn't know if the condition is based on numbers or something else due to the lack of types, it will report all sorts of conditionals within a JSX expression.

TODO: add dangerous cases here

This can be avoided by:

  • casting the condition to bool: {!!someValue && <Something />}
  • transforming the binary expression into a ternary expression which returns null for falsy values: {someValue ? <Something /> : null}

This rule is autofixable, check the Options section to read more about the different strategies available.

Examples of incorrect code for this rule:

const Component = ({ count, title }) => {
  return <div>{count && title}</div>
}
const Component = ({ count }) => {
  return <div>{count && <span>There are {count} results</span>}</div>
}
const Component = ({ elements }) => {
  return <div>{elements.length && <List elements={elements}/>}</div>
}
const Component = ({ nestedCollection }) => {
  return (
    <div>
      {nestedCollection.elements.length && <List elements={nestedCollection.elements} />}
    </div>
  )
}
const Component = ({ elements }) => {
  return <div>{elements[0] && <List elements={elements}/>}</div>
}
const 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.
const Component = ({ someBool }) => {
  return <div>{someBool && <Results>{numberA+numberB}</Results>}</div>
}

Examples of correct code for this rule:

const 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.
const Component = ({ customTitle }) => {
  return <div>{customTitle || defaultTitle}</div>
}
const Component = ({ elements }) => {
  return <div>There are {elements.length} elements</div>
}
const Component = ({ elements, count }) => {
  return <div>{!count && 'No results found'}</div>
}
const Component = ({ elements }) => {
  return <div>{!!elements.length && <List elements={elements}/>}</div>
}
const Component = ({ elements }) => {
  return <div>{Boolean(elements.length) && <List elements={elements}/>}</div>
}
const Component = ({ elements }) => {
  return <div>{elements.length > 0 && <List elements={elements}/>}</div>
}
const Component = ({ elements }) => {
  return <div>{elements.length ? <List elements={elements}/> : null}</div>
}

Options

The supported options are:

validStrategies

An array containing "cast", "ternary" or both (default: ["ternary", "cast"]) - Decide which strategies are considered valid to prevent leaked renders (at least 1 is required). The "cast" option will cast to boolean the condition of the JSX expression. The "ternary" option transforms the binary expression into a ternary expression returning null for falsy values. The first option from the array will be used as autofix, so the order of the values matter.

It can be set like:

{
  // ...
  "react/jsx-no-leaked-zero": [<enabled>, { "validStrategies": ["ternary", "cast"] }]
  // ...
}

Assuming the following options: { "validStrategies": ["ternary"] }

Examples of incorrect code for this rule, with the above configuration:

const Component = ({ count, title }) => {
  return <div>{count && title}</div>
}
const Component = ({ count, title }) => {
  return <div>{!!count && title}</div>
}

Examples of correct code for this rule, with the above configuration:

const Component = ({ count, title }) => {
  return <div>{count ? title : null}</div>
}

Assuming the following options: { "validStrategies": ["cast"] }

Examples of incorrect code for this rule, with the above configuration:

const Component = ({ count, title }) => {
  return <div>{count && title}</div>
}
const Component = ({ count, title }) => {
  return <div>{count ? title : null}</div>
}

Examples of correct code for this rule, with the above configuration:

const Component = ({ count, title }) => {
  return <div>{!!count && title}</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.

Further Reading