17

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?

3
  • 2
    You need to make it as a ternary operator. Something like { list.length ? <div>List rendered</div> : ""} should work for you. Commented Mar 12, 2020 at 11:00
  • array.length is a javascript thing not a react thing. add a condition {list.length>0 && } . it will work fine Commented Mar 12, 2020 at 11:26
  • Yes, I know this case resolved by many solutions. But I need why with this case. Commented Mar 12, 2020 at 11:31

3 Answers 3

27

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

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, for an empty array, 0 is returned by the line { list.length && <div>List rendered</div> }.

While list.length is evaluated as falsy here, 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 the ignored values, you may return a boolean from your leftmost expression:

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

Or cast the value returned by the expression to a boolean, 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>

Sign up to request clarification or add additional context in comments.

Comments

7

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.

Comments

3

I am a bit late to answer it but i would like to express my understandings.

As other answer by @sp00m explains clearly that it is not related to React but it is a feature of javascript.

What it does?

When the left side is falsy then it will take the value of it as in your case it will be 0 because of the [].length. This causes to print "0" in the DOM.

Solution:

You can make it for a truthy expectation like [].length > 0 or [].length !== 0 or !![].length or make a ternary operator to show the component dom.
The last one converts the falsy/truthy values to a boolean value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.