Search code examples
javascriptreactjsreact-bootstrap

React conditional rendering only partially happening


I have a react component that is displaying the results of an array as a Badge (from Bootstrap React library). In the condition, I'm checking if the length of array is greater than zero and rendering the results using a map function. I wanted to add additional text to also display on the condition but for some reason it is not displaying the h1 tag yet the badges are being displayed. Why isn't it displaying the h1 tag??

render() {
   const arr = this.state.items;
   return( 
    <Card>
     <Card.Body>
      <div>
       {arr.length > 0 && <h1>Additional Text</h1> &&
        arr.map((item) => 
        <Badge key={item.toString()} pill variant='primary'>
          {item}
        </Badge>
       }
     </div>
    </Card.Body>
   </Card>
);

Solution

  • You are using an And short circuit evaluation, which evaluates each expression (before the &&) and returns the outcome if it's falsy, or returns the last one if all others are truthy.

    In this case the result of the entire expression is the product of the map when there's an array, since the H1 expression results in an object, which is always truthy.

    To render the H1 as well use two separate expressions:

    render() {
       const arr = this.state.items;
       return( 
        <Card>
         <Card.Body>
          <div>
           {arr.length > 0 && <h1>Additional Text</h1>}
           {arr.length > 0 &&
            arr.map((item) => 
            <Badge key={item.toString()} pill variant='primary'>
              {item}
            </Badge>
           }
         </div>
        </Card.Body>
       </Card>
    );
    

    Another option is to move all conditionally rendered expressions to another function, and call it when the expression is truthy:

    renderBadges(arr) {
      return (
        <>
          <h1>Additional Text</h1>
          {arr.map((item) => (
            <Badge key={item.toString()} pill variant='primary'>
              {item}
            </Badge>
          )}
        </>
      );
    }
    
    render() {
       const arr = this.state.items;
       return( 
        <Card>
         <Card.Body>
          <div>
           {arr.length > 0 && this.renderBadges(arr)}
         </div>
        </Card.Body>
       </Card>
    );