Alexey Tseitlin
Alexey Tseitlin

Reputation: 1309

JSX loop in React

Making a React app that will show colored circles. But when I add a for loop it stopped working. That is wrong here?

I am using babel and JSX. This is an exercise from a book - Learning React by Kirupa Chinnathambi

var colors = ["#393E41", "#E94F37", "#1C89BF", "#A1D363", "#85FFC7", "#297373", "#FF8552", "#A40E4C"];

var renderData = [];

// STOPED WORKING AFTER THIS LOOP
for (var i = 0; i < colors.length; i++) {
  renderData.push(< Circle color = {colors[i]} />);
  }

  let Circle = React.createClass({
    render: function() {
      let styles = {
        background: this.props.color,
        width: 60,
        height: 60,
        borderRadius: "50%"
      }
      return ( 
      <div style={styles}></div>
      )
    }
  });

  ReactDOM.render( 
  <div> {renderData} </div>, window.add);
<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>

<div id="add"></div>

Upvotes: 1

Views: 368

Answers (4)

Andrew Kovalenko
Andrew Kovalenko

Reputation: 6710

Basically, you use the <Circle> component, which is not initialized yet. Other words, you try to access Circle, but its value is undefined.

JavaScript has a language feature called hoisting, which allows you to reference variables and functions before you declare them but result can be really surprising if you don't understand hoisting rules.

Briefly, JS interpreter puts all variables and functions declaration to the top of the scope they declared in. For example, code:

console.log(a)
let a = 1; 

is interpreted as:

let a;
console.log(a)  // value of a is undefined here 
a = 1;

To fix you example just move your component definition above the code which uses it.

let Circle = React.createClass({
  render: function() {
    let styles = {
      background: this.props.color,
      width: 60,
      height: 60,
      borderRadius: "50%"
    }
    return ( 
      <div style={styles}></div>
    )
  } 
});

for (var i = 0; i < colors.length; i++) {
  renderData.push(< Circle color = {colors[i]} />);
}

Upvotes: 0

paqash
paqash

Reputation: 2314

Placing the loop after the definition works for me:

var colors = ["#393E41", "#E94F37", "#1C89BF", "#A1D363", "#85FFC7", "#297373", "#FF8552", "#A40E4C"];

var renderData = [];


  let Circle = React.createClass({
    render: function() {
      let styles = {
        background: this.props.color,
        width: 60,
        height: 60,
        borderRadius: "50%"
      }
      return ( 
      <div style={styles}></div>
      )
    }
  });
  
// STOPED WORKING AFTER THIS LOOP
for (var i = 0; i < colors.length; i++) {
  renderData.push(<Circle color ={colors[i]} />);
  }

  ReactDOM.render( 
  <div> {renderData} </div>, window.add);
<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>

<div id="add"></div>

Upvotes: 1

Alexey Tseitlin
Alexey Tseitlin

Reputation: 1309

The for loop should be after component definition

Upvotes: 1

Perpetualcoder
Perpetualcoder

Reputation: 13571

Since you are working on an exercise here are some pointers:

  1. Use colors.map to return jsx where you create circle components, you can wrap this behavior in a renderCircles function
  2. You may actually create a container element called App so that ReactDOM.render becomes very trivial

Best of luck.

Upvotes: 0

Related Questions