web-dev-qa-db-fra.com

React.js crée une boucle dans Array

J'essaie d'afficher une table de 10 joueurs. Je récupère les données via ajax et les transmets comme accessoires à mon enfant.

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>
    );
  }
});

Maintenant, j'ai besoin d'un composant de liste pour rendre les joueurs:

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>
    )
  }
});

Ce qui me donne un Uncaught TypeError: Cannot read property 'map' of undefined.

Je ne suis pas du tout sûr de ce qui se passe, le journal de ma console affiche les données correctes mais, d'une manière ou d'une autre, je ne peux pas y accéder dans le retour.

Qu'est-ce que je rate ?

33
Mini John

Dans le composant CurrentGame, vous devez modifier l'état initial, car vous essayez d'utiliser la boucle pour participants, mais cette propriété est undefined, c'est pourquoi vous obtenez une erreur.,

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

aussi, comme player dans .map est Object vous devriez en obtenir les propriétés

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

Example

39
Alexander T.

À la résolution de @Alexander, le problème est lié au chargement de données async. Vous effectuez un rendu immédiat et les participants ne sont pas chargés tant que l'appel ajax async n'a pas résolu et ne remplit data avec participants.

L’alternative à la solution proposée serait d’empêcher le rendu tant que les participants n'existeraient pas, par exemple:

    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>
        );
    }
16
Dan W

Vous pouvez simplement faire un contrôle conditionnel avant de faire une carte comme

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

Maintenant, un .map peut être créé de deux manières différentes, mais le contrôle conditionnel est toujours requis, comme

.map avec retour

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

.map sans retour

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

les deux fonctionnalités ci-dessus fait la même chose

1
Hemadri Dasari