1969

I'm trying to do something like the following in React JSX (where ObjectRow is a separate component):

<tbody>
    for (var i=0; i < numrows; i++) {
        <ObjectRow/>
    } 
</tbody>

I 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, I am unsure how I would achieve the above (adding a component multiple times).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
B Robster
  • 40,605
  • 21
  • 89
  • 122
  • 66
    It's important to note that in JSX you need the { } tags around your JavaScript Syntax. This may help https://facebook.github.io/react/docs/jsx-in-depth.html#child-expressions. – Isaiah Grey Dec 24 '15 at 18:25
  • 45
    `let todos = this.props.todos.map((todo) => {return

    {todo.title}

    })`
    – OverCoder Jan 15 '17 at 19:58
  • @OverCoder why would you put whole return into {} tag it would be => return

    {todo.title}

    Isn't it ?
    – Pravin Poudel Mar 17 '20 at 07:41
  • 12
    @pravinpoudel actually that answer is old, more like `let todos = this.props.todos.map(t =>

    {t.title}

    )` :)
    – OverCoder Mar 17 '20 at 10:16
  • The "for" doesn't return a value, you need to return an array element for JSX in your example. – Hossein Mohammadi Oct 01 '20 at 16:15
  • You can put any Javascript expression, _any valid unit of code that resolves to a value_, inside jsx curly braces. A typical for loop is not a javascript expression because it does not resolve to value. [expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#expressions) – Josiah Nyarega May 08 '21 at 22:06
  • A great way to think about this is the return value of a `for loop`. A `for loop` doesn't really return anything, which is why we have to push values into an array and return the array. If you're looking for more explanation, checkout [How To Loop Inside React JSX - React FAQ](https://victorofoegbu.com/notes/loop-inside-react-jsx-faq) – Victor Ofoegbu May 25 '21 at 03:35
  • Can anyone please tell me why is this an invalid JSX? – maverick Aug 02 '21 at 08:30
  • you could try something like {numrows.map(numrow => )} the key is there to silence a react warning – since9teen94 Dec 13 '21 at 14:15
  • This comment can be improved. – Steve Smith May 20 '23 at 06:12

84 Answers84

1748

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.

Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25
Sophie Alpert
  • 139,698
  • 36
  • 220
  • 238
1146

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>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Brigand
  • 84,529
  • 20
  • 165
  • 173
715

If you don't already have an array to map() like @FakeRainBrigand's answer, and want to inline this so the source layout corresponds to the output closer than @SophieAlpert's answer:

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

http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview

<tbody>
  {[...Array(10)].map((x, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

Re: 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. I have a documentation issue open to clarify that. But use at your own risk or polyfill.

Vanilla ES5

Array.apply

<tbody>
  {Array.apply(0, Array(10)).map(function (x, i) {
    return <ObjectRow key={i} />;
  })}
</tbody>

Inline IIFE

http://plnkr.co/edit/4kQjdTzd4w69g8Suu2hT?p=preview

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

Combination of techniques from other answers

Keep the source layout corresponding to the output, but make the inlined part more compact:

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

  return (
    <tbody>
      {rows.map(function (i) {
        return <ObjectRow key={i} index={i} />;
      })}
    </tbody>
  );
}

With ES2015 syntax & Array methods

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

<tbody>
  {Array(10).fill(1).map((el, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

(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.

Sophie Alpert
  • 139,698
  • 36
  • 220
  • 238
JMM
  • 26,019
  • 3
  • 50
  • 55
138

Simply using map Array method with ES6 syntax:

<tbody>
  {items.map(item => <ObjectRow key={item.id} name={item.name} />)} 
</tbody>

Don't forget the key property.

danielfeelfine
  • 1,794
  • 1
  • 11
  • 13
115

Using the Array map function is a very common way to loop through an Array of elements and create components according to them in React. This is a great way to do a loop which is a pretty efficient and is a tidy way to do your loops in JSX. It's not the only way to do it, but the preferred way.

Also, don't forget having a unique Key for each iteration as required. The map function creates a unique index from 0, but it's not recommended using the produced index, but if your value is unique or if there is a unique key, you can use them:

<tbody>
  {numrows.map(x=> <ObjectRow key={x.id} />)}
</tbody>

Also, a few lines from MDN if you not familiar with the map function on Array:

map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values, including undefined. It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).

callback is invoked with three arguments: the value of the element, the index of the element, and the Array object being traversed.

If a thisArg parameter is provided to the map, it will be used as callback's this value. Otherwise, the value undefined will be used as its this value. This value ultimately observable by the callback is determined according to the usual rules for determining the this seen by a function.

map does not mutate the array on which it is called (although callback, if invoked, may do so).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alireza
  • 100,211
  • 27
  • 269
  • 172
87

If you're already using lodash, the _.times function is handy.

import React, { Component } from "react";
import Select from "./Select";
import _ from "lodash";

export default class App extends Component {
  render() {
    return (
      <div className="container">
        <ol>
          {_.times(3, (i) => (
            <li key={i}>repeated 3 times</li>
          ))}
        </ol>
      </div>
    );
  }
}
mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • 1
    Only import ```times``` from Lodash, not the entire library. It's okay during development to avoid backwards incompatibility as Lodash releases updates, but in production you're costing seconds importing an entire library. – coder9833idls Jan 12 '22 at 05:20
  • @coder9833idls Might need to switch to `lodash-es` for tree-shaking to work, no? – mpen Jan 12 '22 at 18:41
83

There are multiple ways to go about doing this. JSX eventually gets compiled to JavaScript, so as long as you're writing valid JavaScript, you'll be good.

My answer aims to consolidate all the wonderful ways already presented here:

If you do not have an array of object, simply the number of rows:

Within the return block, creating an Array and using Array.prototype.map:

render() {
  return (
    <tbody>
      {Array(numrows).fill(null).map((value, index) => (
        <ObjectRow key={index}>
      ))}
    </tbody>
  );
}

Outside the return block, simply use a normal JavaScript for loop:

render() {
  let rows = [];
  for (let i = 0; i < numrows; i++) {
    rows.push(<ObjectRow key={i}/>);
  }
  return (
    <tbody>{rows}</tbody>
  );
}

Immediately invoked function expression:

render() {
  return (
    <tbody>
      {(() => {
        let rows = [];
        for (let i = 0; i < numrows; i++) {
          rows.push(<ObjectRow key={i}/>);
        }
        return rows;
      })()}
    </tbody>
  );
}

If you have an array of objects

Within the return block, .map() each object to a <ObjectRow> component:

render() {
  return (
    <tbody>
      {objectRows.map((row, index) => (
        <ObjectRow key={index} data={row} />
      ))}
    </tbody>
  );
}

Outside the return block, simply use a normal JavaScript for loop:

render() {
  let rows = [];
  for (let i = 0; i < objectRows.length; i++) {
    rows.push(<ObjectRow key={i} data={objectRows[i]} />);
  }
  return (
    <tbody>{rows}</tbody>
  );
}

Immediately invoked function expression:

render() {
  return (
    <tbody>
      {(() => {
        const rows = [];
        for (let i = 0; i < objectRows.length; i++) {
          rows.push(<ObjectRow key={i} data={objectRows[i]} />);
        }
        return rows;
      })()}
    </tbody>
  );
}
Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
57

You can also extract outside the return block:

render: function() {
    var rows = [];
    for (var i = 0; i < numrows; i++) {
        rows.push(<ObjectRow key={i}/>);
    } 

    return (<tbody>{rows}</tbody>);
}
47

You might want to checkout React Templates, which does let you use JSX-style templates in React, with a few directives (such as rt-repeat).

Your example, if you used react-templates, would be:

<tbody>
     <ObjectRow rt-repeat="obj in objects"/>
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Etai
  • 1,483
  • 1
  • 11
  • 15
46

If you opt to convert this inside return() of the render method, the easiest option would be using the map( ) method. Map your array into JSX syntax using the map() function, as shown below (ES6 syntax is used).


Inside the parent component:

<tbody>
   { objectArray.map(object => <ObjectRow key={object.id} object={object.value} />) }
</tbody>

Please note the key attribute is added to your child component. If you didn't provide a key attribute, you can see the following warning on your console.

Warning: Each child in an array or iterator should have a unique "key" prop.

Note: One common mistake people do is using index as the key when iterating. Using index of the element as a key is an antipattern, and you can read more about it here. In short, if it's not a static list, never use index as the key.


Now at the ObjectRow component, you can access the object from its properties.

Inside the ObjectRow component

const { object } = this.props

Or

const object = this.props.object

This should fetch you the object you passed from the parent component to the variable object in the ObjectRow component. Now you can spit out the values in that object according to your purpose.


References:

map() method in JavaScript

ECMAScript 6 or ES6

bharadhwaj
  • 2,059
  • 22
  • 35
37

If numrows is an array, it's very simple:

<tbody>
   {numrows.map(item => <ObjectRow />)}
</tbody>

The array data type in React is much better. An array can back a new array, and support filter, reduce, etc.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
lulin
  • 371
  • 3
  • 3
32

There are several answers pointing to using the map statement. Here is a complete example using an iterator within the FeatureList component to list Feature components based on a JSON data structure called features.

const FeatureList = ({ features, onClickFeature, onClickLikes }) => (
  <div className="feature-list">
    {features.map(feature =>
      <Feature
        key={feature.id}
        {...feature}
        onClickFeature={() => onClickFeature(feature.id)}
        onClickLikes={() => onClickLikes(feature.id)}
      />
    )}
  </div>
); 

You can view the complete FeatureList code on GitHub. The features fixture is listed here.

ballade4op52
  • 2,142
  • 5
  • 27
  • 42
Manav Sehgal
  • 321
  • 3
  • 5
  • When dealing with JSON data, such when retrieving data from database using fetch API, I rely on using Array.prototype.map method. It is a convenient and proven way for that purpose. – Lex Soft Mar 15 '19 at 14:32
31

Let us say we have an array of items in your state:

[{name: "item1", id: 1}, {name: "item2", id: 2}, {name: "item3", id: 3}]

<tbody>
    {this.state.items.map((item) => {
        <ObjectRow key={item.id} name={item.name} />
    })}
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JFAP
  • 3,617
  • 1
  • 24
  • 25
  • I think you may need to get rid of the {} after the map(item), that seemed to work them for me. – Ian Dec 10 '16 at 17:22
  • Just a thought: ```{this.state.items?.map((item) => ```, or my favourite syntax stalwart: ```{this.state.items && this.state.items.map((item) =>``` and drop the unnecessary () from ```(item)``` since there is only one parameter. You're going to get frustrated rendering the component asynchronously and not having the local state imported yet. – coder9833idls Jan 12 '22 at 05:23
  • In this case, it will not render any thing. you need to add `return` keyword inside your `{}` or need to remove the `{}`. `{this.state.items.map((item) => {return()})}` or `{this.state.items.map((item) =>())}` – Junaid Javed May 19 '23 at 08:05
31

To loop for a number of times and return, you can achieve it with the help of from and map:

<tbody>
  {
    Array.from(Array(i)).map(() => <ObjectRow />)
  }
</tbody>

where i = number of times


If you want to assign unique key IDs into the rendered components, you can use React.Children.toArray as proposed in the React documentation

React.Children.toArray

Returns the children opaque data structure as a flat array with keys assigned to each child. Useful if you want to manipulate collections of children in your render methods, especially if you want to reorder or slice this.props.children before passing it down.

Note:

React.Children.toArray() changes keys to preserve the semantics of nested arrays when flattening lists of children. That is, toArray prefixes each key in the returned array so that each element’s key is scoped to the input array containing it.

<tbody>
  {
    React.Children.toArray(
      Array.from(Array(i)).map(() => <ObjectRow />)
    )
  }
</tbody>
Community
  • 1
  • 1
Jee Mok
  • 6,157
  • 8
  • 47
  • 80
30

This can be done in multiple ways.

  1. As suggested above, before return store all elements in the array

  2. Loop inside return

    Method 1:

    let container = [];
    let arr = [1, 2, 3] //can be anything array, object
    arr.forEach((val, index) => {
      container.push(
      <div key={index}>
        val
      </div>)
      /**
      * 1. All loop generated elements require a key
      * 2. only one parent element can be placed in Array
      * e.g. container.push(
      *         <div key={index}>
                  val
                </div>
                <div>
                this will throw error
                </div>
            )
      **/
    });
    return (
      <div>
        <div>any things goes here</div>
        <div>{container}</div>
      </div>
    )
    

    Method 2:

    return (
      <div>
        <div>any things goes here</div>
        <div>
          {
            (() => {
              let container = [];
              let arr = [1, 2, 3] //can be anything array, object
              arr.forEach((val, index) => {
                container.push(
                  <div key={index}>
                    val
                  </div>)
              });
              return container;
            })()
          }
        </div>
      </div>
    )
    
abhirathore2006
  • 3,317
  • 1
  • 25
  • 29
  • Yeah. In my current project, I use method 1, i.e using Array.prototype,forEach() method to create HTML select element which is populated by data from database. However, I will more likely replace them with Array.prototype.map() method, as the map method looks more compact (less code). – Lex Soft Mar 15 '19 at 15:08
28

An ECMAScript 2015 / Babel possibility is using a generator function to create an array of JSX:

function* jsxLoop(times, callback)
{
    for(var i = 0; i < times; ++i)
        yield callback(i);
}

...

<tbody>
    {[...jsxLoop(numrows, i =>
        <ObjectRow key={i}/>
    )]}
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Hogan
  • 549
  • 6
  • 6
24

ES2015 Array.from with the map function + key

If you have nothing to .map() you can use Array.from() with the map function to repeat elements:

<tbody>
  {Array.from({ length: 5 }, (value, key) => <ObjectRow key={key} />)}
</tbody>
Community
  • 1
  • 1
Do Async
  • 4,081
  • 1
  • 22
  • 25
21

...Or you can also prepare an array of objects and map it to a function to have the desired output. I prefer this, because it helps me to maintain the good practice of coding with no logic inside the return of render.

render() {
const mapItem = [];
for(let i =0;i<item.length;i++) 
  mapItem.push(i);
const singleItem => (item, index) {
 // item the single item in the array 
 // the index of the item in the array
 // can implement any logic here
 return (
  <ObjectRow/>
)

}
  return(
   <tbody>{mapItem.map(singleItem)}</tbody>
  )
}
ballade4op52
  • 2,142
  • 5
  • 27
  • 42
Rafi Ud Daula Refat
  • 2,187
  • 19
  • 28
21

I use this:

gridItems = this.state.applications.map(app =>
          <ApplicationItem key={app.Id} app={app } />
);

PS: never forget the key or you will have a lot of warnings!

Kate Orlova
  • 3,225
  • 5
  • 11
  • 35
J C
  • 731
  • 7
  • 11
  • Or use the array index if your items don't have an `.Id` property, like `items.map( (item, index) => {item}` – kontur Mar 30 '17 at 09:26
18

You can of course solve with a .map as suggested by the other answer. If you already use Babel, you could think about using jsx-control-statements.

They require a little of setting, but I think it's worth in terms of readability (especially for non-React developer). If you use a linter, there's also eslint-plugin-jsx-control-statements.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jurgo Boemo
  • 1,690
  • 1
  • 15
  • 21
18

Here's a simple solution to it.

var Object_rows = [];
for (var i = 0; i < numrows; i++) {
  Object_rows.push(<ObjectRow />);
}
<tbody>{Object_rows}</tbody>;

No mapping and complex code is required. You just need to push the rows to the array and return the values to render it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Javasamurai
  • 666
  • 7
  • 21
  • 1
    When creating html select element, this similar technique was the one that came to my mind firstly, So I used it, although I use the forEach() method. But when I reread the React doc on topics of Lists and Keys, I found that they use the map() method as also shown by several answers here. This makes me think that it is the preferred way. I agree, since it looks more compact (less code). – Lex Soft Mar 15 '19 at 15:20
18

Simply use .map() to loop through your collection and return <ObjectRow> items with props from each iteration.

Assuming objects is an array somewhere...

<tbody>
  { objects.map((obj, index) => <ObjectRow obj={ obj } key={ index }/> ) }
</tbody>
17

Your JSX code will compile into pure JavaScript code, any tags will be replaced by ReactElement objects. In JavaScript, you cannot call a function multiple times to collect their returned variables.

It is illegal, the only way is to use an array to store the function returned variables.

Or you can use Array.prototype.map which is available since JavaScript ES5 to handle this situation.

Maybe we can write other compiler to recreate a new JSX syntax to implement a repeat function just like Angular's ng-repeat.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
hlissnake
  • 229
  • 2
  • 3
16

I tend to favor an approach where programming logic happens outside the return value of render. This helps keep what is actually rendered easy to grok.

So I'd probably do something like:

import _ from 'lodash';

...

const TableBody = ({ objects }) => {
  const objectRows = objects.map(obj => <ObjectRow object={obj} />);      

  return <tbody>{objectRows}</tbody>;
} 

Admittedly this is such a small amount of code that inlining it might work fine.

Adam Donahue
  • 1,618
  • 15
  • 18
15

Here is a sample from the React documentation, JavaScript Expressions as Children:

function Item(props) {
  return <li>{props.message}</li>;
}

function TodoList() {
  const todos = ['finish doc', 'submit pr', 'nag dan to review'];
  return (
    <ul>
      {todos.map((message) => <Item key={message} message={message} />)}
    </ul>
  );
}

As for your case, I suggest writing like this:

function render() {
  return (
    <tbody>
      {numrows.map((roe, index) => <ObjectRow key={index} />)}
    </tbody>
  );
}

Please notice the key is very important, because React use the key to differ data in array.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sinka Lee
  • 163
  • 1
  • 6
15

You may use .map() in a React for loop.

<tbody>
    { newArray.map(() => <ObjectRow />) }
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ali Raza
  • 1,026
  • 13
  • 20
13

Since you are writing JavaScript syntax inside JSX code, you need to wrap your JavaScript code in curly braces.

row = () => {
   var rows = [];
   for (let i = 0; i<numrows; i++) {
       rows.push(<ObjectRow/>);
   }
   return rows;
}
<tbody>
{this.row()}
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohit Jindal
  • 679
  • 1
  • 10
  • 21
11

I use it like

<tbody>
  { numrows ? (
     numrows.map(obj => { return <ObjectRow /> }) 
    ) : null
  }
</tbody>
ravibagul91
  • 20,072
  • 5
  • 36
  • 59
Sampath
  • 599
  • 5
  • 12
11

You can also use a self-invoking function:

return <tbody>
           {(() => {
              let row = []
              for (var i = 0; i < numrows; i++) {
                  row.push(<ObjectRow key={i} />)
              }
              return row

           })()}
        </tbody>
ballade4op52
  • 2,142
  • 5
  • 27
  • 42
Fba Shad
  • 121
  • 1
  • 3
  • 1
    Using anonymous functions inside render is not considered a good practice in react, as these functions need to be re-created or discarded on each re-render. – Vlatko Vlahek Sep 29 '17 at 07:25
  • @VlatkoVlahek you're mistaking it with function props being re-created each render cycle, which _could_ lead to poorer performance on a large scale. Creating anonymous function anywhere else is not going to affect performance in any significant way. – Emile Bergeron Feb 20 '20 at 16:54
  • 1
    @EmileBergeron This was a while ago haha. I do agree if this is not used as a prop, there is no difference. – Vlatko Vlahek Feb 20 '20 at 18:36
11

If you really want a for loop equivalent (you have a single number, not an array), just use range from Lodash.

Don't reinvent the wheel and don't obfuscate your code. Just use the standard utility library.

import range from 'lodash/range'

range(4);
// => [0, 1, 2, 3]

range(1, 5);
// => [1, 2, 3, 4]
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dart Dega
  • 241
  • 3
  • 8
10

With time, the language is becoming more mature, and we often stumble upon common problems like this. The problem is to loop a Component 'n' times.

{[...new Array(n)].map((item, index) => <MyComponent key={index} />)}

where, n -is the number of times you want to loop. item will be undefined and index will be as usual. Also, ESLint discourages using an array index as key.

But you have the advantage of not requiring to initialize the array before and most importantly avoiding the for loop...

To avoid the inconvenience of item as undefined you can use an _, so that it will be ignored when linting and won't throw any linting error, such as

{[...new Array(n)].map((_, index) => <MyComponent key={index} />)}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pope_maverick
  • 902
  • 8
  • 15
9

When I want to add a certain number of components, I use a helper function.

Define a function that returns JSX:

const myExample = () => {
    let myArray = []
    for(let i = 0; i<5;i++) {
        myArray.push(<MyComponent/>)
    }
    return myArray
}

//... in JSX

<tbody>
    {myExample()}
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
9

Even this piece of code does the same job.

<tbody>
   {array.map(i => 
      <ObjectRow key={i.id} name={i.name} />
   )}
</tbody>
ravibagul91
  • 20,072
  • 5
  • 36
  • 59
Amruth
  • 5,792
  • 2
  • 28
  • 41
9

Array.from is the best way. If you want to create an array of JSX with some length.

function App() {
  return (
    <tbody>
      {Array.from({ length: 10 }, (_, key) => (
        <ObjectRow {...{ key }} />
      ))}
    </tbody>
  );
}

The above example is for when you do not have an array, so if you have an array you should map it in JSX like this:

function App() {
  return (
    <tbody>
      {list.map((item, key) => (
        <ObjectRow {...{ key }} />
      ))}
    </tbody>
  );
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hossein Mohammadi
  • 1,388
  • 11
  • 16
8

You can do something like:

let foo = [1,undefined,3]
{ foo.map(e => !!e ? <Object /> : null )}
Pang
  • 9,564
  • 146
  • 81
  • 122
8

A loop inside JSX is very simple. Try this:

return this.state.data.map((item, index) => (
  <ComponentName key={index} data={item} />
));
Satya Vinay
  • 315
  • 2
  • 15
Amit Chauhan
  • 1,810
  • 3
  • 17
  • 25
8

If you need JavaScript code inside your JSX, you add { } and then write your JavaScript code inside these brackets. It is just that simple.

And the same way you can loop inside JSX/react.

Say:

<tbody>
    {`your piece of code in JavaScript` }
</tbody>

Example:

<tbody>
    { items.map((item, index) => {
        console.log(item)}) ; // Print item
        return <span>{index}</span>;
    } // Looping using map()
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mustkeem K
  • 8,158
  • 2
  • 32
  • 43
8

Below are possible solutions that you can do in React in terms of iterating array of objects or plain array

const rows = [];
const numrows = [{"id" : 01, "name" : "abc"}];
numrows.map((data, i) => {
    rows.push(<ObjectRow key={data.id} name={data.name}/>);
});

<tbody>
    { rows }
</tbody>

Or

const rows = [];
const numrows = [1,2,3,4,5];
for(let i=1, i <= numrows.length; i++){
    rows.push(<ObjectRow key={numrows[i]} />);
};

<tbody>
    { rows }
</tbody>

An even more better approach I became familiar with recent days for iterating an array of objects is .map directly in the render with return or without return:

.map with return

 const numrows = [{"id" : 01, "name" : "abc"}];
 <tbody>
     {numrows.map(data=> {
         return <ObjectRow key={data.id} name={data.name}/>
     })}
</tbody>

.map without return

 const numrows = [{"id" : 01, "name" : "abc"}];
 <tbody>
     {numrows.map(data=> (
         <ObjectRow key={data.id} name={data.name}/>
     ))}
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162
7

React elements are simple JavaScript, so you can follow the rule of JavaScript. You can use a for loop in JavaScript like this:-

<tbody>
    for (var i=0; i < numrows; i++) {
        <ObjectRow/>
    } 
</tbody>

But the valid and best way is to use the .map function. Shown below:-

<tbody>
    {listObject.map(function(listObject, i){
        return <ObjectRow key={i} />;
    })}
</tbody>

Here, one thing is necessary: to define the key. Otherwise it will throw a warning like this:-

Warning.js:36 Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of ComponentName. See "link" for more information.

Zoe
  • 27,060
  • 21
  • 118
  • 148
Jani Devang
  • 1,099
  • 12
  • 20
7

For printing an array value if you don't have the key value par, then use the below code -

<div>
    {my_arr.map(item => <div>{item} </div> )}                    
</div>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Som
  • 1,467
  • 13
  • 11
7

You can try the new for of loop:

const apple = {
    color: 'red',
    size: 'medium',
    weight: 12,
    sugar: 10
}
for (const prop of apple.entries()){
    console.log(prop);
}

Here's a few examples:

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gilbert lucas
  • 519
  • 7
  • 22
7

Unless you declare a function and enclose it with parameters, it is not possible. In a JSXExpression you can only write expressions and cannot write statements like a for(), declare variables or classes, or a if() statement.

That's why function CallExpressions are so in the mood today. My advice: get used to them. This is what I would do:

const names = ['foo', 'bar', 'seba']
const people = <ul>{names.map(name => <li>{name}</li>)}</ul>

Filtering:

const names = ['foo', undefined, 'seba']
const people = <ul>{names.filter(person => !!person).map(name => <li>{name}</li>)}</ul>

if():

var names = getNames()
const people = {names && names.length &&
   <ul>{names.map(name => <li>{name}</li>)}</ul> }

if - else:

var names = getNames()
const people = {names && names.length ?
  <ul>{names.map(name => <li>{name}</li>)}</ul> : <p>no results</p> }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cancerbero
  • 6,799
  • 1
  • 32
  • 24
7

Use the map function.

<tbody> 
   {objects.map((object, i) =>  <ObjectRow obj={object} key={i} />)} 
</tbody>
Zoe
  • 27,060
  • 21
  • 118
  • 148
Sooraj Jose
  • 392
  • 4
  • 12
7

You can do the same directly in the JSX, using map instead of a for-of loop:

render: function() {
const items = ['one', 'two', 'three'];
 return (
  <ul>
     {items.map((value, index) => {
     return <li key={index}>{value}</li>
     })}
 </ul>
 )
}
Force Bolt
  • 1,117
  • 9
  • 9
7

Just do something like this:

<tbody>
    {new Array(numRows).fill("", 0, numRows).map((p, i) => <YourRaw key={i} />)}
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alwani Anis
  • 260
  • 3
  • 11
6

Well, here you go.

{
    [1, 2, 3, 4, 5, 6].map((value, index) => {
        return <div key={index}>{value}</div>
    })
}

All you have to do is just map your array and return whatever you want to render. And please don't forget to use key in the returned element.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
M Shafique
  • 786
  • 7
  • 18
6

try this

<tbody>
  {new Array(numrows).map((row,index)=><ObjectRow key={***someThingUniqe***}/>)} //don't use index as key 
</tbody>

if you wanna know why you shouldn't use indices as keys in react check this

Revan99
  • 396
  • 2
  • 5
  • 11
5
return (
    <table>
       <tbody>
          {
            numrows.map((item, index) => {
              <ObjectRow data={item} key={index}>
            })
          }
       </tbody>
    </table>
);
ravibagul91
  • 20,072
  • 5
  • 36
  • 59
anshu purohit
  • 176
  • 2
  • 10
  • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Donald Duck Jun 19 '17 at 20:06
  • 1
    This will break. You need to close the ObjectRow tag and you are supposed to return something in your map callback. – Giovanni Lobitos Aug 11 '17 at 05:15
5

You can use an IIFE if you really want to literally use a for loop inside JSX.

<tbody>
  {
    (function () {
      const view = [];
      for (let i = 0; i < numrows; i++) {
        view.push(<ObjectRow key={i}/>);
      }
      return view;
    }())
  }
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Giovanni Lobitos
  • 852
  • 7
  • 19
5

@jacefarm If I understand right you can use this code:

<tbody>
    { new Array(numrows).fill(<ObjectRow/>) } 
</tbody>

Either you can use this code:

<tbody>
   { new Array(numrows).fill('').map((item, ind) => <ObjectRow key={ind}/>) } 
</tbody>

And this:

<tbody>
    new Array(numrows).fill(ObjectRow).map((Item, ind) => <Item key={ind}/>)
</tbody>
Bogdan Surai
  • 1,197
  • 14
  • 16
5

Using map in React are best practices for iterating over an array.

To prevent some errors with ES6, the syntax map is used like this in React:

<tbody>
    {items.map((item, index) => <ObjectRow key={index} name={item.name} />)}
</tbody>

Here you call a Component, <ObjectRow/>, so you don't need to put parenthesis after the arrow.

But you can be make this too:

{items.map((item, index) => (
    <ObjectRow key={index} name={item.name} />
))}

Or:

{items.map((item, index) => {
    // Here you can log 'item'
    return (
        <ObjectRow key={index} name={item.name} />
    )
})}

I say that because if you put a bracket "{}" after the arrow React will not throw an error and will display a whitelist.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Quentin Malguy
  • 279
  • 5
  • 6
5

The problem is you don't return any JSX element. There are another solutions for such cases, but I will provide the simplest one: "use the map function"!

<tbody>
  { numrows.map(item => <ObjectRow key={item.uniqueField} />) }
</tbody>

It's so simple and beautiful, isn't it?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
5

I've found one more solution to follow the map render:

 <tbody>{this.getcontent()}</tbody>

And a separate function:

getcontent() {
    const bodyarea = this.state.movies.map(movies => (
        <tr key={movies._id}>
            <td>{movies.title}</td>
            <td>{movies.genre.name}</td>
            <td>{movies.numberInStock}</td>
            <td>{movies.publishDate}</td>
            <td>
                <button
                    onClick={this.deletMovie.bind(this, movies._id)}
                    className="btn btn-danger"
                >
                    Delete
                </button>
            </td>
        </tr>
    ));
    return bodyarea;
}

This example solves many problems easily.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Saad Mirza
  • 1,154
  • 14
  • 22
5

Use {} around JavaScript code within a JSX block to get it to properly perform whatever JavaScript action you are trying to do.

<tr>
  <td>
    {data.map((item, index) => {
      {item}
    })}
  </td>
</tr>

This is kind of vague, but you can swap out data for any array. This will give you a table row and table item for each item. If you have more than just one thing in each node of the array, you will want to target that specifically by doing something like this:

<td>{item.someProperty}</td>

In which case, you will want to surround it with a different td and arrange the previous example differently.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
esewalson
  • 240
  • 3
  • 2
5

There are many solutions posted out there in terms of iterating an array and generating JSX elements. All of them are good, but all of them used an index directly in a loop. We are recommended to use unique id from data as a key, but when we do not have a unique id from each object in the array we will use index as a key, but you are not recommended to use an index as a key directly.

One more thing why we go for .map, but why not .foEach because .map returns a new array. There are different ways of doing .map these days.

Below different versions of using .map illustrates in detail about how to use a unique key and how to use .map for looping JSX elements.

.map without return when returning single a JSX element and unique id from data as a key version:

const {objects} = this.state;

<tbody>
    {objects.map(object => <ObjectRow obj={object} key={object.id} />)}
</tbody>

.map without return when returning multiple JSX elements and unique id from data as a key version

const {objects} = this.state;

<tbody>
    {objects.map(object => (
        <div key={object.id}>
            <ObjectRow obj={object} />
        </div>
    ))}
</tbody>

.map without return when returning a single JSX element and index as a key version:

const {objects} = this.state;

<tbody>
    {objects.map((object, index) => <ObjectRow obj={object} key={`Key${index}`} />)}
</tbody>

.map without return when returning multiple JSX elements and index as a key version:

const {objects} = this.state;

<tbody>
    {objects.map((object, index) => (
        <div key={`Key${index}`}>
            <ObjectRow obj={object} />
        </div>
    ))}
</tbody>

.map with return when returning multiple JSX elements and index as a key version:

const {objects} = this.state;

<tbody>
    {objects.map((object, index) => {
        return (
            <div key={`Key${index}`}>
                <ObjectRow obj={object} />
            </div>
        )
    })}
</tbody>

.map with return when returning multiple JSX elements and unique id from data as a key version:

const {objects} = this.state;

<tbody>
    {objects.map(object => {
        return (
            <div key={object.id}>
                <ObjectRow obj={object} />
            </div>
        )
    })}
</tbody>

The other way is

render() {
  const {objects} = this.state;
  const objectItems = objects.map(object => {
       return (
           <div key={object.id}>
               <ObjectRow obj={object} />
           </div>
       )
  })
  return(
      <div>
          <tbody>
              {objectItems}
          </tbody>
      </div>
   )
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162
5

To provide a more straightforward solution in case you want to use a specific row count which is stored as Integer-value.

With the help of typedArrays we could achieve the desired solution in the following manner.

// Let's create a typedArray with length of `numrows`-value
const typedArray = new Int8Array(numrows); // typedArray.length is now 2
const rows = []; // Prepare rows-array
for (let arrKey in typedArray) { // Iterate keys of typedArray
  rows.push(<ObjectRow key={arrKey} />); // Push to an rows-array
}
// Return rows
return <tbody>{rows}</tbody>;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jimi Pajala
  • 2,358
  • 11
  • 20
5

You can create a new component like below:

Pass key and data to your ObjectRow component like this:

export const ObjectRow = ({key,data}) => {
    return (
      <div>
          ...
      </div>
    );
}

Create a new component ObjectRowList to act like a container for your data:

export const ObjectRowList = (objectRows) => {
    return (
      <tbody>
        {objectRows.map((row, index) => (
          <ObjectRow key={index} data={row} />
        ))}
      </tbody>
    );
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mselmi Ali
  • 1,139
  • 2
  • 18
  • 28
5

I am not sure if this will work for your situation, but often [map][1] 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 the map function:

<tbody>
    {objects.map(function(object, i){
        return <ObjectRow obj={object} key={i} />;
    })}
</tbody>

objects.map is the best way to do a loop, and objects.filter is the best way to filter the required data. The filtered data will form a new array, and objects.some is the best way to check whether the array satisfies the given condition (it returns Boolean).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Varunkumar Gande
  • 599
  • 6
  • 18
  • Can you add the missing link to "map" (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today)? – Peter Mortensen Feb 14 '21 at 15:41
5

You could do the following to repeat a component numrows times

<tbody>{Array(numrows).fill(<ObjectRow />)}</tbody>
king.reflex
  • 313
  • 4
  • 10
5

This is what I used in most of my projects up to now:

const length = 5;
...
<tbody>
    {Array.from({ length }).map((_,i) => (
        <ObjectRow key={i}/>
    ))}
</tbody>
Hayyaun
  • 303
  • 3
  • 10
5

try this one please

<tbody>
   {Array.apply(0, Array(numrows)).map(function (x, i) {
     return <ObjectRow/>;
   })}
</tbody>

or

{[...Array(numrows)].map((x, i) =>
   <ObjectRow/>
)}
5

A one liner (assuming numrows is a number):

<tbody>
  {
    Array(numrows).fill().map(function (v, i) {
      return <ObjectRow/>
    })
  }
</tbody>
ling
  • 9,545
  • 4
  • 52
  • 49
4

If numrows is an array, as the other answers, the best way is the map method. If it's not and you only access it from JSX, you can also use this ES6 method:

<tbody>
    {
      [...Array(numrows).fill(0)].map((value,index)=><ObjectRow key={index} />)
    }
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kamuran Sönecek
  • 3,293
  • 2
  • 30
  • 57
4

You'll want to add elements to an array and render the array of elements.
This can help reduce the time required to re-render the component.

Here's some rough code that might help:

MyClass extends Component {
    constructor() {
        super(props)
        this.state = { elements: [] }
    }
    render() {
        return (<tbody>{this.state.elements}<tbody>)
    }
    add() {
        /*
         * The line below is a cheap way of adding to an array in the state.
         * 1) Add <tr> to this.state.elements
         * 2) Trigger a lifecycle update.
         */
        this.setState({
            elements: this.state.elements.concat([<tr key={elements.length}><td>Element</td></tr>])
        })
    }
}
Shawn Khameneh
  • 472
  • 4
  • 16
4

You have to write in JSX:

<tbody>
    {
        objects.map((object, i) => (
            <ObjectRow obj={object} key={i} />
        ));
    }
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sultan Aslam
  • 5,600
  • 2
  • 38
  • 44
4
<tbody>
   numrows.map((row,index) => (
      return <ObjectRow key={index}/>
   )
</tbody>
vimal ram
  • 133
  • 1
  • 2
  • 8
4
render() {
  const elements = ['one', 'two', 'three'];

  const items = []

  for (const [index, value] of elements.entries()) {
    items.push(<li key={index}>{value}</li>)
  }

  return (
    <div>
      {items}
    </div>
  )
}
Pacific P. Regmi
  • 1,607
  • 19
  • 15
4

There are multiple ways to loop inside JSX

  1. Using a for loop

    function TableBodyForLoop(props) {
      const rows = []; // Create an array to store list of tr
    
      for (let i = 0; i < props.people.length; i++) {
        const person = props.people[i];
        // Push the tr to array, the key is important
        rows.push(
          <tr key={person.id}>
            <td>{person.id}</td>
            <td>{person.name}</td>
          </tr>
        );
      }
    
      // Return the rows inside the tbody
      return <tbody>{rows}</tbody>;
    }
    
  2. Using the ES6 array map method

    function TableBody(props) {
      return (
        <tbody>
          {props.people.map(person => (
            <tr key={person.id}>
              <td>{person.id}</td>
              <td>{person.name}</td>
            </tr>
          ))}
        </tbody>
      );
    }
    
    

Full example: https://codesandbox.io/s/cocky-meitner-yztif

The following React Docs will be helpful

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gsaandy
  • 581
  • 4
  • 8
4

It's funny how people give "creative" answers using a newer syntax or uncommon ways to create an array. In my experience working with JSX, I have seen these tricks only used by inexperienced React programmers.

The simpler the solution - the better it is for future maintainers. And since React is a web framework, usually this type of (table) data comes from the API. Therefore, the simplest and most practical way would be:

const tableRows = [
   {id: 1, title: 'row1'}, 
   {id: 2, title: 'row2'}, 
   {id: 3, title: 'row3'}
]; // Data from the API (domain-driven names would be better of course)
...

return (
   tableRows.map(row => <ObjectRow key={row.id} {...row} />)
);



Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ilyas Assainov
  • 1,901
  • 13
  • 15
4

You can only write a JavaScript expression in a JSX element, so a for loop cannot work. You can convert the element into an array first and use the map function to render it:

<tbody>
    {[...new Array(numrows)].map((e) => (
         <ObjectRow/>
    ))}
</tbody>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vengleab SO
  • 716
  • 4
  • 11
4

Having the JSX content in the map can be clunky syntax. Instead you can do this:

const ObjectRow = ({ ... }) => <tr key={}>...</tr>

const TableBody = ({ objects }) => {
  return <tbody>{objects.map(ObjectRow)}</tbody>;
}

This is shorthand for

{ objects.map(object => ObjectRow(object))

If ObjectRow is set up to take the same keys that are in the object, this will work great.

Note - You may need to set the key prop when the ObjectRow is rendered. It can't be passed in through the function call.


More notes - I've run into a few places where this technique is a bad idea. For example, it doesn't go through the normal create component path and won't default prop values for example, so do beware. Still, it's handy to know about and is useful sometimes.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mark Swardstrom
  • 17,217
  • 6
  • 62
  • 70
4

If you are used to Angular and want a more React-like approach:

Try using this simple component with auto hashing and optional trackBy similar to Angular's.

Usage:

<For items={items}>
    {item => <div>item</div>}
</For>

Custom key/trackBy:

<For items={items} trackBy={'name'}>
    {item => <div>item</div>}
</For>

Definition:

export default class For<T> extends Component<{ items: T[], trackBy?: keyof T, children: (item: T) => React.ReactElement }, {}> {
    render() {
        return (
            <Fragment>
                {this.props.items.map((item: any, index) => <Fragment key={this.props.trackBy ?? item.id ?? index}>{this.props.children(item)}</Fragment>)}
            </Fragment>
        );
    }
}

React Dev Tools:

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
4

use map to looping

 Array.map(arrayItem => {
return <ObjectRow arrayItem={arrayItem}/> // pass array item in component
})
4

you can use .map() for loop in reactjs

    <tbody>
        {items.map((value, index) => {
          return <li key={index}>{value}</li>
        })}
      </tbody>
)
3

I have seen one person/previous answer use .concat() in an array, but not like this...

I have used concat to add to a string and then just render the JSX content on the element via the jQuery selector:

let list = "<div><ul>";

for (let i=0; i<myArray.length; i++) {
    list = list.concat(`<li>${myArray[i].valueYouWant}</li>`);
}

list = list.concat("</ul></div>);

$("#myItem").html(list);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sao
  • 1,835
  • 6
  • 21
  • 40
3

Maybe the standard of today maximum developer, use a structure like this:

 let data = [
  {
    id: 1,
    name: "name1"
  },
  {
    id: 2,
    name: "name2"
  },
  {
    id: 3,
    name: "name3"
  },
  {
    id: 100,
    name: "another name"
  }
];

export const Row = data => {
  return (
    <tr key={data.id}>
      <td>{data.id}</td>
      <td>{data.name}</td>
    </tr>
  );
};

function App() {
  return (
    <table>
      <thead>
        <tr>
          <th>Id</th>
          <th>Name</th>
        </tr>
      </thead>
      <tbody>{data.map(item => Row(item))}</tbody>
    </table>
  );
}

In the JSX, write your JavaScript action inside HTML or any code here, {data.map(item => Row(item))}, use single curly braces and inside a map function. Get to know more about map.

And also see the following output here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Md. Abu Sayed
  • 2,396
  • 2
  • 18
  • 26
3
const numrows = [1, 2, 3, 4, 5];

cosnt renderRows = () => {
    return numros.map((itm,index) => <td key={index}>{itm}</td>)
}

return <table>
    ............
    <tr>
        {renderRows()}
    </tr>
</table>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kamalesh biswas
  • 883
  • 8
  • 9
3

Inside your render or any function and before return, you can use a variable to store JSX elements. Just like this -

const tbodyContent = [];
for (let i=0; i < numrows; i++) {
    tbodyContent.push(<ObjectRow/>);
}

Use it inside your tbody like this:

<tbody>
    {
        tbodyContent
    }
</tbody>

But I'll prefer map() over this.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Piyush Rana
  • 631
  • 5
  • 8
  • Ohh I almost forgot that map return an array of jsx element and this is not, so will update my answer soon until then use map method. – Piyush Rana Nov 25 '20 at 08:11
  • Updated the solution, this should work fine. – Piyush Rana Nov 27 '20 at 12:19
  • *Why* do you prefer *map()*? – Peter Mortensen Feb 14 '21 at 16:10
  • Map by default return a new array and you can directly use it inside your JSX and get the same result as you will get using `for` loop with less headache. If you use `for` loop you need to declare a separate array variable for storing result calculated inside loop, that's not the case using `map` that is why I'll prefer map over normal loop for react. – Piyush Rana Feb 18 '21 at 03:35
3
function PriceList({ self }) {
    let p = 10000;
    let rows = [];
    for(let i=0; i<p; i=i+50) {
        let r = i + 50;
        rows.push(<Dropdown.Item key={i} onClick={() => self.setState({ searchPrice: `${i}-${r}` })}>{i}-{r} &#8378;</Dropdown.Item>);
    }
    return rows;
}

<PriceList self={this} />
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

Simple way

You can put numrows in state and use map() instead of a for loop:

{this.state.numrows.map((numrows , index) => {
      return (
        <ObjectRow
          key={index}
        />
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mansour lotfi
  • 524
  • 2
  • 7
  • 22
2

It is looping through a set of data, creating a new React Component for each item in the data set. This can be achieved using the map() method of JavaScript.

For example, if you have an array of objects called "data" and a React Component called "ObjectRow":

const rows = data.map((item, index) => <ObjectRow key={index} {...item} />);

Then you can render the rows inside the tbody tag like this:

<tbody>{rows}</tbody>
Anurag V
  • 51
  • 3
2

Hello my developer friend! you can use this for make a loop looks like "for" inside the JSX react for essay! just use crt c plus crt p inside your project and enjoy!

<>{Array(6).fill({}).map((d, i) => (<p>Hi from item number {i}</p>)))}</>
-1

Below code will help you to create Loop inside JSX with passing unique key props

import React, { Children, Fragment } from 'react';

export const ObjectRow = ({ data }) => (
 <div>
    <Fragment>{data}</Fragment>
 </div>
);


/** Wrapping your list inside React.Children.toArray allows you to not 
pass unique key props.
It will be dynamically generated from Virtual Dom to Real Dom */

export const ObjectRowListComponent = (objectRows) => (
<tbody>
    {Children.toArray(objectRows.map((row) => <ObjectRow data={row} />))}
</tbody>
);
Rohan Shukla
  • 533
  • 1
  • 4
  • 16
-7

You can not use any loop or other extra methods directly in JSX. Instead what you can do is make separate function for that and make loop statement and in that function return your component Example for above code:

function renderObjectRow (){
   for (var i=0; i < numrows; i++) {
       return  <ObjectRow/>
     } 
}

<tbody>
{renderObjectRow()}
</tbody>


  • 1
    It is important to understand that this answer is not only wrong but will hurt you performance quite bit, because the function will be called and recreate the components on each render. – Fabio Nettis Jul 07 '23 at 14:40