Comment éviter les "enfants avec la même clé," quand le remplacement de l'état dans ReactJs composant
J'ai créé un Réagir Composant qui rend un ensemble de sous-éléments étant donné un tableau d'id. Le tableau des id est maintenu dans l'état du composant parent, puis-je lancer quelques appels ajax basé sur l'id pour récupérer des données à rendre. Les données extraites sont stockées dans un autre tableau de données dans l'état. Le rendu des composants utiliser l'id comme clé.
Les valeurs peuvent changer en fonction des actions à l'extérieur du composant, donc j'utilise setState sur le composant à remplacer le tableau. La mise à jour de l'id de l'etat sera probablement contenir certains des mêmes identifiants comme dans le tableau d'origine. En même temps, je vide le "tableau de données", de sorte que tout sera rendu à nouveau.
Quand je le fais parfois, j'ai la clé d'alerte:
Avertissement: flattenChildren(...): Rencontré deux enfants avec le même
clé. Enfant les clés doivent être uniques; lorsque deux enfants partagent une clé, seulement
le premier enfant sera utilisé.
Le nouveau tableau ne contient pas de doublons. Alors, pourquoi fait-il et que puis-je faire pour éviter cela?
Edit: Ajout de code à la demande. Note: je suis en utilisant le Infini Défilement module. Cela pourrait-il être la cause?
État Initial:
getInitialState: function() {
return {
hasMore: true,
num: 0,
movieIds: this.props.movieIds,
movies: []
};
},
Fonction rendu:
render: function() {
var InfiniteScroll = React.addons.InfiniteScroll;
return (
<InfiniteScroll
pageStart={0}
loadMore={this.loadMore}
threshold='20'
hasMore={this.state.hasMore}>
<ul className="movieList">
{this.state.movies}
</ul>
</InfiniteScroll>
);
}
Simplifié de la charge plus:
comp = this;
$.ajax( {
url: url,
contentType: "json",
success: function (data) {
var m = createMovieLi(data);
var updatedMovies = comp.state.movies;
updatedMovies[num] = m;
comp.setState({movies: updatedMovies});
}
});
Et enfin lors de la mise à jour en dehors du composant:
movieBox.setState({
hasMore: true,
num: 0,
movieIds: filteredIds,
movies: []
});
- Donner un exemple minimal de code qui montre le problème. C'est probablement une solution simple, mais totalement dépendant de votre code.
Vous devez vous connecter pour publier un commentaire.
J'ai compris mon erreur, et il n'avait rien à voir avec Réagissent en soi. C'était un cas classique de manquant javascript à l'intérieur fermeture à boucle.
En raison de la possibilité de doublons, j'ai stocké chaque ajax en réponse à la fenêtre.localStorage, sur la movieId. Ou alors j'ai pensé.
À Réagir Inifinite de Défilement de chaque élément de votre liste est établie de manière séquentielle avec un appel à la loadMore-fonction. L'intérieur de cette fonction, j'ai fait mon appel ajax, et stocké le résultat dans le cache du navigateur. Le code cherché quelque chose comme ceci:
Pouvez-vous repérer l'erreur? Lors de l'ajax, des retours d'appel, movieId n'est plus ce qu'elle est. Donc j'arrive à la fin de stocker les données par la mauvaise id, et d'obtenir un peu étrange de Réagir avertissements en retour. Parce que cela a été fait à l'intérieur de la loadMore fonction appelée par le InfiniteScroll-module, je n'étais pas au courant que cette fonction n'a pas été correctement évalués.
J'ai corrigé par l'ajout d'un Immédiatement invoquées par l'expression de fonction.
Je ne voudrais pas utiliser l'ID à partir d'un back-end comme la clé de la propriété de Réagir. Si vous le faites, vous êtes en s'appuyant sur une logique qui est un peu loin de votre composant assurez-vous que vos clés sont uniques. Si ils les touches ne sont pas uniques, vous pouvez rompre réagir de rendu, donc c'est assez important.
C'est pourquoi vous devriez, à mon avis, il suffit de coller à l'aide de l'index à l'intérieur d'une boucle for ou similaire pour définir des propriétés de clé. De cette façon, vous savez qu'ils ne peuvent jamais être non unique, et c'est la façon la plus simple de faire exactement cela.
Sans savoir exactement comment votre Id de travail, il est impossible de dire quelle est la cause de la non-unique s'affrontent ici. Toutefois, depuis
key
est juste pour permettre de Réagir correctement identifier les éléments, et rien d'autre, il n'a pas vraiment de sens pour elle d'être autre chose qu'un simple comptage ou de l'index.React.Children.map
pour parcourir une liste d'objets, comment voulez-vous obtenir un numéro d'index à utiliser? Pouvez-vous utiliser quoi que ce soit à partir de lamap
fonction? Ou souhaitez-vous tout simplement en créer un vous-même?map
. Exemple: jsfiddle.net/69z2wepo/4120