简体   繁体   中英

Conditional Statement Within Map Loop

In ReactJS, I am trying to call an if statement within a map loop. An example code is this:

var items = ['abc', '123', 'doe', 'rae', 'me'];
return (
  <div>

       {items.map((item, index) => (
            <span dangerouslySetInnerHTML={{ __html: item }}></span>

            {index % 2:
                <h1>Test Output/h1>
            }

        ))}

  </div>
}

Except I keep getting his error:

 Module build failed: SyntaxError: Unexpected token, expected , (73:11)
web_1  | 
web_1  |   71 |                     <span dangerouslySetInnerHTML={{ __html: item }}></span>
web_1  |   72 |                     
web_1  | > 73 |                     {index % 2:
web_1  |      |                     ^

How can I call an if statement within a loop?

First, you can't return multiple sibling elements as JSX without a parent container, unless you put them into an array (though you can't return arrays from render methods until React adds support for returning fragments).

This is invalid:

return (
  <div>First sibling</div>
  <div>Second sibling</div>
);

These are both valid:

return (
  <div>
      <div>First sibling</div>
      <div>Second sibling</div>
  <div>
);

// vs.
// (notice this requires adding keys)

return ([
  <div key={1}>First sibling</div>,
  <div key={2}>Second sibling</div>
]);

Second, if you want to use a conditional statement to render components, you have to do it like this:

{(index % 2 === 0) &&
  <div>This will render when index % 2 === 0</div>
}

The reason this works is that the && operator in JavaScript evaluates to the second operand (your JSX in this case) if the first operand is truthy. You can also use ternary statements, like this:

{(index % 2 === 0) ?
  <div>This will render when index % 2 === 0</div>
:
  <div>This will render when index % 2 !== 0</div>
}


Putting this all together

var items = ['abc', '123', 'doe', 'rae', 'me'];
return (
  <div>

       {items.map((item, index) => (
            <div>
                <span dangerouslySetInnerHTML={{ __html: item }}></span>

                {(index % 2 === 0) &&
                    <h1>Test Output/h1>
                }
            </div>

        ))}

  </div>
}


[Edit] Important note

I should mention that whenever you're rendering an array of elements using something like items.map(...) , you should really be assigning a unique key to each element in the list that you're rendering:

{items.map((item, index) => (
  <div key={item.get('id')}>Item #{index}</div>
))}

The reason is that React does some optimizations here to make rendering (and re-rendering) lists less costly. If it sees a list that used to be composed of keys 0, 1, 2 and you've done some operation to reorder the items in your state, so that now the keys are passed to your map function in the order 0, 2, 1 , it won't rebuild the DOM to reflect the changed order, but rather will just swap the DOM nodes (which is faster).

This leads to why you don't want to use index as a key for your elements, UNLESS you know that their order won't change. Let's say you used the iteration index as your keys:

{items.map((item, index) => (
  <div key={index}>Item #{index}</div>
))}

Now, if your items change order, they'll be output with the keys in the same order (index 0 will always be the first index, index 1 will always be the second index, and so on) but with different text inside each div. React will do a diff with the real DOM, notice that the value of each div has changed, and rebuild that entire chunk of the DOM from scratch.

This gets even worse if your list elements include something with state that isn't reflected in the DOM, like an <input> . In that case, React will rebuild the DOM, but any text the user has input in those fields will remain exactly where it was! Here's an example from Robin Pokorny that demonstrates what can go wrong (sourced from this article ):

https://jsbin.com/wohima/edit?js,output

I guess your condition for the if is index % 2 == 1 which shows the Heading when index is an odd number

{index % 2 == 1 && (
     <h1>Test Output/h1>
)}

Official Documentation

But in your case, you are writing this if condition within {}. That means, you are now writing the JavaScript. So, just use the JavaScript syntax.

if(index % 2 == 1){
   return(
    <div>
      <span dangerouslySetInnerHTML={{ __html: item }}></span>
      <h1>Test Output/h1>
    </div>);
}

Update: As Jaromanda pointed out, you need to return one element. So, wrapping your <span> and <h1> into <div> will gives a single element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM