Think of it like you're just calling JavaScript functions. You can't use a for loop where the arguments to a function call would go:
return tbody(
for (let i = 0; i < numrows; i++) {
ObjectRow()
}
)
See how the function tbody is being passed a for loop as an argument – leading to a syntax error.
But you can make an array, and then pass that in as an argument:
const rows = [];
for (let i = 0; i < numrows; i++) {
rows.push(ObjectRow());
}
return tbody(rows);
You can basically use the same structure when working with JSX:
const rows = [];
for (let i = 0; i < numrows; i++) {
// note: we are adding a key prop here to allow react to uniquely identify each
// element in this array. see: https://reactjs.org/docs/lists-and-keys.html
rows.push(<ObjectRow key={i} />);
}
return <tbody>{rows}</tbody>;
Incidentally, my JavaScript example is almost exactly what that example of JSX transforms into. Play around with Babel REPL to get a feel for how JSX works.
Answer from Sophie Alpert on Stack OverflowThink of it like you're just calling JavaScript functions. You can't use a for loop where the arguments to a function call would go:
return tbody(
for (let i = 0; i < numrows; i++) {
ObjectRow()
}
)
See how the function tbody is being passed a for loop as an argument – leading to a syntax error.
But you can make an array, and then pass that in as an argument:
const rows = [];
for (let i = 0; i < numrows; i++) {
rows.push(ObjectRow());
}
return tbody(rows);
You can basically use the same structure when working with JSX:
const rows = [];
for (let i = 0; i < numrows; i++) {
// note: we are adding a key prop here to allow react to uniquely identify each
// element in this array. see: https://reactjs.org/docs/lists-and-keys.html
rows.push(<ObjectRow key={i} />);
}
return <tbody>{rows}</tbody>;
Incidentally, my JavaScript example is almost exactly what that example of JSX transforms into. Play around with Babel REPL to get a feel for how JSX works.
I am not sure if this will work for your situation, but often map is a good answer.
If this was your code with the for loop:
<tbody>
for (var i=0; i < objects.length; i++) {
<ObjectRow obj={objects[i]} key={i}>
}
</tbody>
You could write it like this with map:
<tbody>
{objects.map(function(object, i){
return <ObjectRow obj={object} key={i} />;
})}
</tbody>
ES6 syntax:
<tbody>
{objects.map((object, i) => <ObjectRow obj={object} key={i} />)}
</tbody>
Can I use a for loop with JSX? To render something 3 times?
Hi
) More on reddit.comHow to generate react html in a loop [duplicate]
reactjs - Create HTML from for loop in JSX with React.js - Stack Overflow
reactjs - Using for loop render some Html elements in React render function - Stack Overflow
let sampleOutput =()=>{
return
for(let i=0;i<3;i++){<p>hi</p>}
}
trying to display hi 3 times inside
return()in my component. I know how to .map or .forEach for objects and arrays but what if my store or variable is just a number, I assume forloop doesnt work?
The only problem is that Arrays.forEach does not return anything. If you change your handleEvents function to look more like
if(array.length > 0){
return array.map(function(each){
return(<h1>hello {each.name}</h1>)
})
} else {
return []
}
This should return an h1. The map function will return a list of the elements returned
Or using forEach
handleEvents = (array) => {
if(array.length > 0){
let tempArray = []
array.forEach(function(each){
tempArray.push(<h1>hello {each.name}</h1>)
})
return tempArray
}
On a recent project I did something similar, but with table rows/columns.
var TableBody = React.createClass({
render: function(){
var columns = this.props.columns;
var data = this.props.data;
return (
<tbody>
{data.map(function(item, idx){
return <TableRow key={idx} data={item} columns={columns}/>;
})}
</tbody>
)
}
});
My <TableRow /> component looks like:
var TableRow = React.createClass({
render: function() {
var columns = this.props.columns;
var data = this.props.data;
var td = function(item) {
return columns.map(function(c, i) {
return <td key={i}>{item[c]}</td>;
}, this);
}.bind(this);
return (
<tr key={data}>{ td(data) }</tr>
)
}
});
Two things jump out at me when I look at your code.
The first is that you are returning an array of React components from the renderTemplates function. This may be okay depending on how you use the output. The key to remember is that the return value from your component's render function must be a single React component (e.g., if you wrap this result in another JSX tag, you're okay.)
Secondly, it appears that you are not letting data flow from the top-level component on down; specifically, that you do not use the Row component to pass data to Column components. This is what makes writing your loop so difficult. Instead of trying to manage both Rows and Columns, you need only to pass the data needed for a single row to a Row component. The Row component will then pass each piece of data to a Column component. This removes the need to juggle opening and closing tags and simplifies the code overall.
Following is an example implementation of what I have described. I use table-related tags for rendering, but you can use divs or whatever is most appropriate for you. At the time of writing, there isn't much information about what is in templates, so I've created a silly little example to use.
var KvpColumn = React.createClass({
render: function() {
return <td>{this.props.kvp.key}: {this.props.kvp.value}</td>;
}
});
var KvpRow = React.createClass({
render: function() {
return (
<tr>
{this.props.items.map(function(item) {
return <KvpColumn key={item.key} kvp={item}/>;
})}
</tr>
);
}
});
var ObjectIDsTable = React.createClass({
render: function() {
var templates = this.props.templates;
var propertyNames = Object.getOwnPropertyNames(templates);
var group = [];
var rows = [];
var cols = Number(this.props.cols) || 2;
for(var i = 0; i < propertyNames.length; i++) {
var key = propertyNames[i];
group.push({key: key, value: templates[key]});
if(group.length === cols) {
rows.push(<KvpRow key={group[0].key} items={group}/>);
group = [];
}
}
if(group.length > 0) { // catch any leftovers
rows.push(<KvpRow key={group[0].key} items={group}/>);
}
return <table>{rows}</table>;
}
});
// something silly as a simple example
var templates = { a: 'b', c: 'd', e: 'f', g: 'h', i: 'j' };
React.render(<ObjectIDsTable templates={templates} cols="2"/>, document.getElementById('app'));
If you have access to Underscore or lodash, you can simplify the logic in ObjectIDsTable a bit further (and avoid writing loops altogether!):
var ObjectIDsTable = React.createClass({
render: function() {
var templates = this.props.templates;
var rows = _.chain(Object.getOwnPropertyNames(templates))
.map(function(key) { return { key: key, value: templates[key] }; })
.chunk(this.props.cols || 2)
.map(function(group) { return <KvpRow key={group[0].key} items={group}/>; })
.value();
return <table>{rows}</table>;
}
});
You can see this in action on Plunker.