I’m trying to convert a jQuery component to React.js and one of the things I’m having difficulty with is rendering n number of elements based on a for loop.
I understand this is not possible, or recommended and that where an array exists in the model it makes complete sense to use map
. That’s fine, but what about when you do not have an array? Instead you have numeric value which equates to a given number of elements to render, then what should you do?
Here’s my example, I want to prefix a element with an arbitrary number of span tags based on it’s hierarchical level. So at level 3, I want 3 span tags before the text element.
In javascript:
for (var i = 0; i < level; i++) { $el.append('<span class="indent"></span>'); } $el.append('Some text value');
I can’t seem to get this, or anything similar to work in a JSX React.js component. Instead I had to do the following, first building a temp array to the correct length and then looping the array.
React.js
render: function() { var tmp = []; for (var i = 0; i < this.props.level; i++) { tmp.push(i); } var indents = tmp.map(function (i) { return ( <span className='indent'></span> ); }); return ( ... {indents} "Some text value" ... ); }
Surely this can’t be the best, or only way to achieve this? What am I missing?
Advertisement
Answer
Updated: As of React > 0.16
Render method does not necessarily have to return a single element. An array can also be returned.
var indents = []; for (var i = 0; i < this.props.level; i++) { indents.push(<span className='indent' key={i}></span>); } return indents;
OR
return this.props.level.map((item, index) => ( <span className="indent" key={index}> {index} </span> ));
Docs here explaining about JSX children
OLD:
You can use one loop instead
var indents = []; for (var i = 0; i < this.props.level; i++) { indents.push(<span className='indent' key={i}></span>); } return ( <div> {indents} "Some text value" </div> );
You can also use .map and fancy es6
return ( <div> {this.props.level.map((item, index) => ( <span className='indent' key={index} /> ))} "Some text value" </div> );
Also, you have to wrap the return value in a container. I used div in the above example
As the docs say here
Currently, in a component’s render, you can only return one node; if you have, say, a list of divs to return, you must wrap your components within a div, span or any other component.