En passant clefs pour les enfants dans React.js

Je suis en cours d'exécution à travers une réagir tutoriel sur la tutsplus qui est un peu vieux, et le code ne fonctionne pas comme il a été écrit à l'origine. Je suis tout à fait ok avec ce qu'il me force à apprendre de façon plus autonome, cependant j'ai passé du temps sur un bug que je n'arrive pas à comprendre. Le bug consiste à ne pas être en mesure de passer sur une clé objets, ce qui empêche mon programme à partir de la mise à jour de l'état de l'objet correct.

Tout d'abord voici le repo si vous souhaitez exécuter ce code et de le voir en action: https://github.com/camerow/react-voteit

J'ai un enfant composant qui ressemble à ceci:

var FeedItem = React.createClass({

  vote: function(newCount) {
    console.log("Voting on: ", this.props, " which should have a key associated.");

    this.props.onVote({
      key: this.props.key,
      title: this.props.title,
      description: this.props.desc,
      voteCount: newCount
    });
  },

  voteUp: function() {
    var count = parseInt(this.props.voteCount, 10);
    var newCount = count + 1;
    this.vote(newCount);
  },

  voteDown: function() {
    var count = parseInt(this.props.voteCount, 10);
    var newCount = count - 1;
    this.vote(newCount);
  },

  render: function() {
    var positiveNegativeClassName = this.props.voteCount >= 0 ?
                                    'badge badge-success' :
                                    'badge badge-danger';
    return (
      <li key={this.props.key} className="list-group-item">
        <span className={positiveNegativeClassName}>{this.props.voteCount}</span>
        <h4>{this.props.title}</h4>
        <span>{this.props.desc}</span>
        <span className="pull-right">
          <button id="up" className="btn btn-sm btn-primary" onClick={this.voteUp}>&uarr;</button>
          <button id="down" className="btn btn-sm btn-primary" onClick={this.voteDown}>&darr;</button>
        </span>
      </li>
    );
  }

});

Maintenant, quand quelqu'un frappe le bouton de vote le comportement souhaité est le FeedItem.vote() la méthode pour envoyer un objet à l'Alimentation principale composante:

var FeedList = React.createClass({

  render: function() {
    var feedItems = this.props.items;

    return (
      <div className="container">
        <ul className="list-group">

          {feedItems.map(function(item) {
            return <FeedItem key={item.key}
                             title={item.title}
                             desc={item.description}
                             voteCount={item.voteCount}
                             onVote={this.props.onVote} />
          }.bind(this))}
        </ul>
      </div>
    );
  }

});

Qui doit passer qui touche au travers du composant parent du onVote fonction:

var Feed = React.createClass({
getInitialState: function () {
var FEED_ITEMS = [
{
key: 1,
title: 'JavaScript is fun',
description: 'Lexical scoping FTW',
voteCount: 34
}, {
key: 2,
title: 'Realtime data!',
description: 'Firebase is cool',
voteCount: 49
}, {
key: 3,
title: 'Coffee makes you awake',
description: 'Drink responsibly',
voteCount: 15
}
];
return {
items: FEED_ITEMS,
formDisplayed: false
}
},
onToggleForm: function () {
this.setState({
formDisplayed: !this.state.formDisplayed
});
},
onNewItem: function (newItem) {
var newItems = this.state.items.concat([newItem]);
//console.log("Creating these items: ", newItems);
this.setState({
items: newItems,
formDisplayed: false,
key: this.state.items.length
});
},
onVote: function (newItem) {
//console.log(item);
var items = _.uniq(this.state.items);
var index = _.findIndex(items, function (feedItems) {
//Not getting the correct index.
console.log("Does ", feedItems.key, " === ", newItem.key, "?");
return feedItems.key === newItem.key;
});
var oldObj = items[index];
var newItems = _.pull(items, oldObj);
var newItems = this.state.items.concat([newItem]);
//newItems.push(item);
this.setState({
items: newItems
});
},
render: function () {
return (
<div>
<div className="container">
<ShowAddButton displayed={this.state.formDisplayed} onToggleForm={this.onToggleForm}/>
</div>
<FeedForm displayed={this.state.formDisplayed} onNewItem={this.onNewItem}/>
<br />
<br />
<FeedList items={this.state.items} onVote={this.onVote}/>
</div>
);
}
});

Ma logique s'appuie sur le pouvoir de concilier les clés dans la onVote fonction, cependant, la clé de prop n'est pas correctement transmis. Donc ma question est, comment puis-je passer sur elles par le biais de ce flux " pour mon composant parent?

Note: n'hésitez pas à signaler d'autres problèmes ou d'améliorer la conception de décision, ou absolue des stupidités. Ou même que je me suis poser la mauvaise question.

Impatience une belle exploration de ce sympathique cadre.

key a une signification spéciale pour Réagir. Il n'est pas mis à la disposition du composant via this.props.key autant que je sache. Vous devez utiliser un autre prop nom. Ou, si vous voulez vraiment utiliser la valeur de la clé, ajouter un supplément de l'hélice avec le même, que vous pouvez ensuite accéder à l'intérieur du composant. Voir facebook.github.io/réagir/docs/...
Ahh, ok, qui a aidé énormément. J'avais lu que la documentation déjà, mais était un peu perplexe. Donc, pour préciser que c'est ok pour moi pour définir un accessoire key mais il devrait ressembler <FeedItem key={item.id} />? Ou devrais-je éviter key en tout?
Encore cet avertissement Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of FeedList. See https://fb.me/react-warning-keys for more information., bien que la modification de toutes les instances de key à id m'a permis de passer cette prop.
Oh, ayant le bien key est parfaitement bien. Le prop key est spécial pour Réagir. Donc <FeedItem key={item.id} /> permet de Réagir avec la réconciliation des composants. Toutefois, le béton instance de FeedItem n'a pas vraiment d'avoir accès à la valeur de key, et il ne devrait pas en avoir, puisqu'il est d'aucun intérêt pour elle. Si vous souhaitez passer l'id du composant afin qu'il puisse y accéder, choisissez un autre prop nom.
Vous devez définir key ainsi: <FeedItem key={item.id} id={item.id} />. Il peut paraître redondant, mais ils servent à des fins différentes: key est pour Réagir et id est pour votre composant.

OriginalL'auteur camerow | 2015-05-26