Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "0" is rendered on short-circuit evaluation of `array.length && ...`

Currently, I see behavior like this:

render() {
   const list = [];
   return (
      <div>
         { list.length && <div>List rendered</div> }
      </div>
   )
}

My expected is nothing rendered with that condition, but string "0" rendered (string "0" is list.length). I don't know why. Anybody can help me explain this case to React?

like image 293
aldenn Avatar asked Mar 12 '20 10:03

aldenn


2 Answers

That's basically the way, short-circuit evaluation is designed:

As logical expressions are evaluated left to right, they are tested for possible "short-circuit" evaluation using the following rules:

(some falsy expression) && expr is short-circuit evaluated to the falsy expression

Thus, 0 is returned with the line { list.length && <div>List rendered</div> }.

While it is also evaluated as falsy it is not ignored on render as opposed to false, null, undefined or true.

So, if you want your short-circuit expression to return one of ignored values, you may do it this way:

{ list.length>0 && <div>List rendered</div> }

Or cast 0 to false, like that:

{ !!list.length && <div>List rendered</div> }

Following is a quick demo as a proof of concept:

const { render } = ReactDOM

const Component = () => {
  const list = []
  return (
      <div>
         <div>Rendered on <code>{`list.length && <div>List rendered</div>`}</code>:{ list.length && <div>List rendered</div> }</div>
         <div>Rendered on <code>{`list.length>0 && <div>List rendered</div>`}</code>:{ list.length>0 && <div>List rendered</div> }</div>
         <div>Rendered on <code>{`!!list.length && <div>List rendered</div>`}</code>:{ !!list.length && <div>List rendered</div> }</div>
      </div>
   )
}

render (<Component />, document.getElementById('root'))
code {background-color: grey; color:white;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>
like image 188
Yevgen Gorbunkov Avatar answered Sep 20 '22 00:09

Yevgen Gorbunkov


This isn't related to React really, but rather to JavaScript directly:

const output = list.length && "foobar";

If list.length is falsy, then output will take its value (so 0 in this case), and not false as one might think.

like image 43
sp00m Avatar answered Sep 24 '22 00:09

sp00m