Disons que j'ai un composant de vue qui a un rendu conditionnel:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
MyInput ressemble à ceci:
class MyInput extends React.Component {
...
render(){
return (
<div>
<input name={this.props.name}
ref="input"
type="text"
value={this.props.value || null}
onBlur={this.handleBlur.bind(this)}
onChange={this.handleTyping.bind(this)} />
</div>
);
}
}
Disons que employed
c'est vrai. Chaque fois que je le change sur false et que l'autre vue est rendue, seule unemployment-duration
est réinitialisée. unemployment-reason
Obtient également prérempli avec la valeur de job-title
(si une valeur a été donnée avant que la condition ne change).
Si je change le balisage dans la deuxième routine de rendu en quelque chose comme ceci:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Il semble que tout fonctionne bien. On dirait que React ne parvient tout simplement pas à différencier «titre du poste» et «raison du chômage».
S'il vous plaît dites-moi ce que je fais de mal ...
data-reactid
sur chacun des élémentsMyInput
(ouinput
, comme on le voit dans DOM) avant et après leemployed
commutateur?<div>
. Lesdata-reactid
attributs semblent être différents à la fois sur le div d'encapsulation et sur le champ d'entrée.job-title
l'entrée obtient l'iddata-reactid=".0.1.1.0.1.0.1"
, tandis que l'unemployment-reason
entrée obtient l'iddata-reactid=".0.1.1.0.1.2.1"
unemployment-duration
?reactid
attributs sont identiques surjob-title
etunemployment-reason
, tandis que dans le second exemple (avec le diff span) ils sont différents.unemployment-duration
l'reactid
attribut est toujours unique.Réponses:
Ce qui se passe probablement, c'est que React pense qu'un seul
MyInput
(unemployment-duration
) est ajouté entre les rendus. En tant que tel,job-title
jamais n'est remplacé par leunemployment-reason
, ce qui explique également pourquoi les valeurs prédéfinies sont permutées.Lorsque React effectue la comparaison, il déterminera quels composants sont nouveaux et lesquels sont anciens en fonction de leur
key
propriété. Si aucune clé de ce type n'est fournie dans le code, elle générera la sienne.La raison pour laquelle le dernier extrait de code que vous fournissez fonctionne est que React doit essentiellement changer la hiérarchie de tous les éléments sous le parent
div
et je pense que cela déclencherait un nouveau rendu de tous les enfants (c'est pourquoi cela fonctionne). Si vous aviez ajouté lespan
vers le bas au lieu du haut, la hiérarchie des éléments précédents ne changerait pas et ces éléments ne seraient pas rendus (et le problème persisterait).Voici ce que dit la documentation officielle de React :
Vous devriez être en mesure de résoudre ce problème en fournissant
key
vous-même un élément unique au parentdiv
ou à tous lesMyInput
éléments.Par exemple:
OU
Maintenant, quand React fera la différence, il verra que les
divs
sont différents et le restituera en incluant tous ses enfants (1er exemple). Dans le 2ème exemple, le diff sera un succès surjob-title
etunemployment-reason
puisqu'ils ont maintenant des clés différentes.Vous pouvez bien sûr utiliser toutes les clés de votre choix, à condition qu'elles soient uniques.
Mise à jour août 2017
Pour un meilleur aperçu du fonctionnement des clés dans React, je recommande fortement de lire ma réponse à Comprendre les clés uniques dans React.js .
Mise à jour novembre 2017
Cette mise à jour aurait dû être publiée il y a quelque temps, mais l'utilisation de chaînes littérales dans
ref
est désormais obsolète. Par exempleref="job-title"
devrait maintenant être plutôtref={(el) => this.jobTitleRef = el}
(par exemple). Voir ma réponse à l' avertissement de dépréciation en utilisant this.refs pour plus d'informations.la source
it will determine which components are new and which are old based on their key property.
- c'était ... la clé ... à ma compréhensionChangez la clé du composant.
Le composant sera démonté et une nouvelle instance de Component sera montée car la clé a changé.
edit : Documenté sur vous n'avez probablement pas besoin d'un état dérivé :
la source
Utilisez
setState
dans votre vue pour changer laemployed
propriété de l'état. Ceci est un exemple de moteur de rendu React.la source
Je travaille sur Crud pour mon application. C'est comme ça que je l'ai fait J'ai Reactstrap comme dépendance.
Quelques React Hooks là-dedans
la source