score:3

Accepted answer

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>
);

score:0

from what i see you are trying to use conditional statements wrong. from the docs here.

expr1 && expr2 means if expr1 can be converted to true, returns expr2; else, returns expr1.

i.e your first expression arr.length > 0 returns true so, your second expression is evaluated <h1>...</h1> which is also evaluated true. therefore, final expression is evaluated and returned.

so to display both the components you could use fragments or as others have suggested using multiple conditionals or wrapping in a div.

{
  arr.length > 0 && 
  <>
  <h1>additional text</h1>
  {
     arr.map((item) => 
        <badge key={item.tostring()} pill variant='primary'>
          {item}
        </badge>
  }
  </>        
}

here, <> and </> are shorthands for <react.fragment> and </react.fragment> and will give you the same tree structure you might have wanted.

score:1

this is because arr.length > 0 && <h1>additional text</h1> evaluates to true and you see the tags.

a cleaner approach would be to do something like this (just a suggestion, there are many other possible and equally correct ways):

const getpills = (items) => {
    const pills = [<h1>additional text</h1>];
    items.foreach(item => {
        pills.push(
            <badge key={item.tostring()} pill variant='primary'>
                {item}
            </badge>
        );
    })
    return pills;
};

render() {
   const arr = this.state.items;
   return( 
    <card>
     <card.body>
      <div>
       {arr.length ? getpills(arr) : ''}
     </div>
    </card.body>
   </card>
);

score:1

try wrapping your content in a div as you are having the same condition, so no need to duplicate condition, like this:

render() {
   const arr = this.state.items;
   return( 
    <card>
     <card.body>
       {arr.length > 0 && (
       <div>
        <h1>additional text</h1>
        {arr.map((item) => 
          <badge key={item.tostring()} pill variant='primary'>
            {item}
          </badge>
        }
       </div>)
    </card.body>
   </card>
);

score:1

because && checks its preceding condition or statement to be truthy

 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>
);

Related Query

More Query from same tag