React.js create loop through Array

135,171

Solution 1

In CurrentGame component you need to change initial state because you are trying use loop for participants but this property is undefined that's why you get error.,

getInitialState: function(){
    return {
       data: {
          participants: [] 
       }
    };
},

also, as player in .map is Object you should get properties from it

this.props.data.participants.map(function(player) {
   return <li key={player.championId}>{player.summonerName}</li>
   // -------------------^^^^^^^^^^^---------^^^^^^^^^^^^^^
})

Example

Solution 2

As @Alexander solves, the issue is one of async data load - you're rendering immediately and you will not have participants loaded until the async ajax call resolves and populates data with participants.

The alternative to the solution they provided would be to prevent render until participants exist, something like this:

    render: function() {
        if (!this.props.data.participants) {
            return null;
        }
        return (
            <ul className="PlayerList">
            // I'm the Player List {this.props.data}
            // <Player author="The Mini John" />
            {
                this.props.data.participants.map(function(player) {
                    return <li key={player}>{player}</li>
                })
            }
            </ul>
        );
    }

Solution 3

You can simply do conditional check before doing map like

{Array.isArray(this.props.data.participants) && this.props.data.participants.map(function(player) {
   return <li key={player.championId}>{player.summonerName}</li>
   })
}

Now a days .map can be done in two different ways but still the conditional check is required like

.map with return

{Array.isArray(this.props.data.participants) && this.props.data.participants.map(player => {
   return <li key={player.championId}>{player.summonerName}</li>
 })
}

.map without return

{Array.isArray(this.props.data.participants) && this.props.data.participants.map(player => (
   return <li key={player.championId}>{player.summonerName}</li>
 ))
}

both the above functionalities does the same

Share:
135,171
Mini John
Author by

Mini John

⚡️Growth Engineer ~ full stack dev ~ build fast, fix later ~ #Data Junkie ~ #Analytics Obsessed. Data &amp; Growth @anyroad

Updated on November 05, 2020

Comments

  • Mini John
    Mini John over 3 years

    I'm trying to display a Table of 10 Players. I get the data from via ajax and pass it as props to my Child.

    var CurrentGame = React.createClass({
    
      // get game info
      loadGameData: function() {
        $.ajax({
          url: '/example.json',
          dataType: 'json',
          success: function(data) {
            this.setState({data: data});
          }.bind(this),
          error: function(xhr, status, err) {
            console.error('#GET Error', status, err.toString());
          }.bind(this)
        });
      },
    
      getInitialState: function(){
        return {data: []};
      },
    
      componentDidMount: function() {
        this.loadGameData();
      },
    
      render: function() {
        return (
          <div className="CurrentGame">
            <h1> Current Game Information</h1>
            <PlayerList data={this.state.data}/>
          </div>
        );
      }
    });
    

    Now I need a List Component to Render the Players:

    var PlayerList = React.createClass({
    
    
      render: function() {
    
        // This prints the correct data
        console.log(this.props.data);
    
        return (
          <ul className="PlayerList">
            // I'm the Player List {this.props.data}
            // <Player author="The Mini John" />
    
            {
              this.props.data.participants.map(function(player) {
                return <li key={player}>{player}</li>
              })
            }
          </ul>
        )
      }
    });
    

    Which gives me a Uncaught TypeError: Cannot read property 'map' of undefined.

    I'm kind of unsure what is happening, my console log displays the correct data but somehow I can't access it in the return.

    What am I missing ?