2

I'm new to react and am trying to implement a simple for loop, as demonstrated in this other stackoverflow post. However, I cannot seem to make it work. I just want to run the component 5 (or any number of) times rather than map over an array or similar.

DEMO: https://stackblitz.com/edit/react-ekmvak

Take this example here:

index.js:

import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';
import Test from './test';

class App extends Component {
  constructor() {
    super();
    this.state = {
      name: 'React'
    };
  }

  render() {
    return (
      <div>
        for (var i=0; i < 5; i++) {
        <Test />
    } 
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

test.js

import React from "react";

export default function Test() {
  return (
    <p>test</p>
  );
}

Can anyone tell me where I'm going wrong? I've tried to copy the other stackoverflow post and tried test() also. I still get this error:

Error in index.js (18:27) Identifier expected.

Thanks for any help here.

Anurag Srivastava
  • 14,077
  • 4
  • 33
  • 43
user8758206
  • 2,106
  • 4
  • 22
  • 45

5 Answers5

3

You're trying to use plain Javascript in JSX. You have the right idea but your syntax is wrong. Instead, move your Javascript code (for loop) out to your render() method (above the return())

render() {
  let items = []
  for (let i = 0; i < 5; i++) {
    items.push(<Test key={i} />)
  }

  return (
    <div>
      {items}
    </div>
  );
}

Few things to note here:

  • Components that are being iterated over, need a unique key property. In this case, we can use the current value of i
  • Elements can be rendered in JSX by wrapping them in curly braces, shown above. { items }
bruh
  • 2,205
  • 7
  • 30
  • 42
2

You need a returned value inside the JSX to be able to display anything, here's how you can do that:

const Test = () => {
  return (
    <p>test</p>
  );
}

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      name: 'React'
    };
  }

  render() {
    return (
       <div> { Array.from(Array(5)).map(el => <Test />) } </div>
    );
  }
}

// Render it
ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Anurag Srivastava
  • 14,077
  • 4
  • 33
  • 43
2

JSX will accept you any valid JavaScript expressions, Declarative vs Imperative Programming maybe this source can help you. You can create a declarative solution like those shown by the other colleagues (and the best solution), and also you can wrap your imperative solution into a function or method.

const Test = () => {
  return (
    <p>test</p>
  );
}

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      name: 'React'
    };
  }

  createElements = () => {
    const elments = [];
    for (var i=0; i < 5; i++) {
      elments.push(<Test />)
    } 
    return elements;
  }

  render() {
    return (
      <div>
        {this.createElements()}
      </div>
    );
  }
}

// Render it
ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Alejandro
  • 104
  • 4
1

You can't use a for loop like this in your return. I would recommend you using a map for this and looping over an array. You can do this by simply creating an array and directly mapping over it :

[...Array(totalSteps)].map(el => el {
  return (
    <Test />
)
})

You will have to surround this whole block in {}. This will create an array of totalSteps items and return totalSteps <Test />. So if totalSteps is 5, you'll be rendering that component 5 times. This is how your final component should look like :

render() {
    return (
      <div>
      {[...Array(totalSteps)].map(el => el {
        return (
          <Test />
        )
      })}
      </div>
    );
  }
Trisma
  • 735
  • 6
  • 19
  • 1
    Imo it's nicer to use `Array.fill()` instead of the spread operator if you want to use `map`. Also assigning `undefined` to `el` is unecessary. In the end `Array(totalSteps).fill().map((_, i) => )` seems much more comprehensible. – Leo Apr 14 '20 at 17:43
  • 1
    Also note that each element in an array of react childs should have a unique key property. – Leo Apr 14 '20 at 17:50
0

For Dynamic Implementation, you can just pass an object to the parameter and display its different values in different components. We will use map to iterate through the array of objects. Following is the example code in this regard:

return (
<>
{userData.map((data,index)=>{
  return <div key={index}>
    <h2>{data.first_name} {data.last_name}</h2>
    <p>{data.email}</p>
  </div>
})}

</>

In my scenerio, the following code helped me to generically generate multiple cards on the same page using a loop (map):

{data.map((data1, id)=> {
       return <div key={id} className='c-course-container-card'>
       <Courses 
          courseid = {data1.courseid}
          courselink = {data1.courselink}
          img = {data1.imgpath}
          coursetitle = {data1.coursetitle}
          coursedesc = {data1.coursedesc}
        />
        </div>
 })}

Hope it helps! :)

Hassan Shahzad
  • 455
  • 6
  • 14