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>
reactjs - Is it a bad idea to use for loop/non ES6 for React - Stack Overflow
For loops ever in React?
reactjs - javascript (ES6): any more efficient way than "for loops"? - Stack Overflow
Modify React Elements in ES6 using a for loop and setTimeout
Videos
You can't really avoid looking at every car and you can't avoid looking at every spec in the car because you want to test each of those. You can avoid looping over the preferences every time by using a Set.
So this may or may not be faster, but it's much simpler and much easier to understand because the code almost reads like English: filter cars where every spec is in the preferences:
// Car objects
const cars = [{
name: "Honda",
category: "eco",
specs: ["green", "fast","automatic"]
},
{
name: "BMW",
category: "sport",
specs: ["blue", "fast","automatic"]
}
]
const preferences = new Set(["green", "fast", "4x4", "automatic", "panorama"])
let filtered = cars.filter(car => car.specs.every(spec => preferences.has(spec)))
console.log(filtered)
-- EDIT --
Using the data in the OP:
const array_intersect = (a, b) => a.filter( i => (b.indexOf(i) >= 0) )
const a_contains_b = (a, b) => array_intersect(a, b).length == b.length
var cars = [{
name: "Honda",
category: "eco",
specs: ["green", "fast", "automatic"]
},
{
name: "BMW",
category: "sport",
specs: ["blue", "fast", "automatic"]
}
]
const preferences = ["green", "fast", "4x4", "automatic", "panorama"]
let filtered = cars.filter(car => a_contains_b(preferences, car.specs))
console.log(filtered);
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.
Here is more functional example with some ES6 features:
'use strict';
const React = require('react');
function renderArticles(articles) {
if (articles.length > 0) {
return articles.map((article, index) => (
<Article key={index} article={article} />
));
}
else return [];
}
const Article = ({article}) => {
return (
<article key={article.id}>
<a href={article.link}>{article.title}</a>
<p>{article.description}</p>
</article>
);
};
const Articles = React.createClass({
render() {
const articles = renderArticles(this.props.articles);
return (
<section>
{ articles }
</section>
);
}
});
module.exports = Articles;
i am trying to create a site with a database where you are able to see the data from the database. When i get the data i do a for loop for the data and create the elements but i dont know how i can show them withn a for loop because i dont know a good way to do this in the render function.The Code:
function ReadData(data {)
for (let i = 0; i < data.length; i++ {
var Date = data[i].created;
const Button = React.createElement('div', { id: "But " + data[i].id, className: "PostButton", onClick: (event) => event.stopPropagation((window.location.href = Post?/${data[i].name}/${data[i].id}))});
const Main = React.createElement('div', { id: "post " + data[i].id }); //document.getElementById(But ${data[i].id}).appendChild(Main);
const info = React.createElement('div', { id: "Post Info " + i }); //document.getElementById("post " + data[i].id).appendChild(info);
const Profile = React.createElement('button', { id: "NameDisplay", className: "SameLine", onClick: (event) => event.stopPropagation(window.location.href = Profile?${data[i].name})}, ${data[i].name}); } })some of the code like the onclick does not work but that is because this was first a normal javascript project but i am now moving it to react so you see a window.location.href while this does not work with react but ignore that part.
i had working js code for the regular site but that create multiple objects for some reason that code looked like this:
function ReadData(data){
for (let i = 0; i < data.length; i++) {
var Date = data[i].created;
let Button = document.createElement("div");
Button.id = "But " + data[i].id;
Button.className = "PostButton";
Button.onclick = function () { event.stopPropagation(window.location.href = `Post?/${data[i].name}/${data[i].id}`) } document.getElementById("Posts").appendChild(Button);
let Main = document.createElement("div");
Main.id = "post " + data[i].id;
document.getElementById(`But ${data[i].id}`).appendChild(Main);
let info = document.createElement("div");
info.id = "Post Info " + i;
document.getElementById("post " + data[i].id).appendChild(info);
info.innerHTML = `<button class='SameLine' id='NameDisplay' onclick="event.stopPropagation(window.location.href='Profile?${data[i].name}')">${data[i].name}</button>` } }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?