Tags

Other

Looping inside React JSX

Problem

Let's try to understand what problem are we solving right here. We are trying to do something like the following in React JSX (where ObjectRow is a separate component):

    for (var i=0; i < numrows; i++) {

}

We can realize and understand why this isn't valid JSX, since JSX maps to function calls. However, coming from "template" land and being new to JSX, We are unsure how we would achieve the above (adding a component multiple times).

Solution

We should think of it like we're just calling JavaScript functions. We can't put a for loop inside a function call:

return tbody(
    for (var i = 0; i < numrows; i++) {

        ObjectRow();
    }

)

But we can make an array, and then pass that in:

var rows = [];
for (var i = 0; i < numrows; i++) {

    rows.push(ObjectRow());
}

return tbody(rows);

We can use basically the same structure when working with JSX:

var rows = [];
for (var i = 0; i < numrows; i++) {

    // note: we add 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();
}
return {rows};

Incidentally, the above JavaScript example is almost exactly what that example of JSX transforms into. Playing around with Babel REPL will help us to get a feel for how JSX works.

Alternatively, often map is a good answer. If this was our code with the for loop:

    for (var i=0; i < objects.length; i++) {
        
}

We could write it like this with map :

{objects.map(function(object, i){ return ; })}

ES6 syntax:

    {objects.map((object, i) => )}

If we don't already have an array to map() like the above solution, and want to inline this so the source layout corresponds to the output closer than first ever solution:

With ES2015 (ES6) syntax (spread and arrow functions)

{[...Array(10)].map((x, i) =>
    

)}

Regarding transpiling with Babel, its caveats page says that Array.from is required for spread, but at present ( v5.8.23 ) that does not seem to be the case when spreading an actual Array . We do have a documentation issue open to clarify that. But use at your own risk or polyfill.
Demo on Plnkr

Vanilla ES5

Array.apply() 
{Array.apply(0, Array(10)).map(function (x, i) {
    return ;
  })}

Inline IIFE

{(function (rows, i, len) { while (++i <= len) { rows.push() } return rows; })([], 0, 10)}

Demo on Plnkr

Combination of techniques from other answers

Keeping the source layout corresponding to the output, but let's make the inlined part more compact:

render: function () {
  var rows = [], i = 0, len = 10;
  while (++i <= len) rows.push(i);
  return (
    
      {rows.map(function (i) {
        return ;
})}

);

}

With ES2015 syntax & Array methods

With Array.prototype.fill you could do this as an alternative to using spread as illustrated above:

{Array(10).fill(1).map((el, i) => )}

(I think you could actually omit any argument to fill() , but I'm not 100% on that.) Thanks to @FakeRainBrigand for correcting my mistake in an earlier version of the fill() solution (see revisions).

key

In all cases the key attr alleviates a warning with the development build, but isn't accessible in the child. You can pass an extra attr if you want the index available in the child. See Lists and Keys for discussion.

That is indeed less verbose than the (ES5) IIFE example we used, but it's considerably more verbose than the [...Array(x)].map(() => )) version, which I think is the most elegant, and why I featured it. The great point is that there doesn't appear to be anything about JSX that precludes it, so it depends what React or another consumer of transformed JSX does with the children arguments, which we couldn't say without looking at the source.

Summary

When we have a worse code with loop and custom directive elements and we need to loop them on the front end, we have more than three ways of implementing it in React, React JSX, Vanilla JavaScript, ES2015 and Array methods and key is something valuable here and we need to include them in the loops to avoid further errors caused by the React transpiler.

WRITTEN BY PRAVEEN KUMAR

Thanks to Praveen Kumar for being our guest writer this week.

Who Are Ronald James?

We are a leading niche digital & tech recruitment specialist for the North East of England. We Specialise in the acquisition of high-performing technology talent across a variety of IT sectors including Digital & Technology Software Development.

Our ultimate goal is to make a positive impact on every client and candidate we serve - from the initial call and introduction, right up to the final delivery, we want our clients and candidates to feel they have had a beneficial and productive experience.

Contact our Team

If you’re looking to start your journey in sourcing talent or find your dream job, you’ll need a passionate, motivated team of experts to guide you. Check out our Jobs page for open vacancies. If interested, contact us or call 0191 300 6501 for a quick chat with our team.

Let's be Friends!

Follow us on our blog, Facebook, LinkedIn, Twitter or Instagram to follow industry news, events, success stories and new blogs releases.

 

Back to Blog

</Follow Us>