J'ai un simple composant de réaction avec la forme qui, je crois, a une entrée contrôlée:
import React from 'react';
export default class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (
<form className="add-support-staff-form">
<input name="name" type="text" value={this.state.name} onChange={this.onFieldChange('name').bind(this)}/>
</form>
)
}
onFieldChange(fieldName) {
return function (event) {
this.setState({[fieldName]: event.target.value});
}
}
}
export default MyForm;
Lorsque j'exécute mon application, l'avertissement suivant s'affiche:
Avertissement: MyForm est en train de transformer une entrée non contrôlée de type texte en contrôlé. Les éléments d’entrée ne doivent pas passer de non contrôlés à contrôlée (ou vice versa). Décidez entre utiliser un contrôle ou élément d'entrée non contrôlé pour la durée de vie du composant
Je crois que mon entrée est contrôlée car elle a une valeur. Je me demande ce que je fais mal
J'utilise React 15.1.0
Je crois que mon entrée est contrôlée car elle a une valeur.
Pour qu'une entrée soit contrôlée, sa valeur doit correspondre à celle d'une variable d'état.
Cette condition n'est pas remplie initialement dans votre exemple car this.state.name
n'est pas défini initialement. Par conséquent, l'entrée est initialement non contrôlée. Une fois que le gestionnaire onChange
est déclenché pour la première fois, this.state.name
est défini. À ce stade, la condition ci-dessus est satisfaite et l'entrée est considérée comme contrôlée. Cette transition de non contrôlé à contrôlé produit l'erreur vue ci-dessus.
En initialisant this.state.name
dans le constructeur:
par exemple.
this.state = { name: '' };
l'entrée sera contrôlée dès le début, corrigeant le problème. Voir Réagir aux composants contrôlés pour plus d'exemples.
Sans rapport avec cette erreur, vous ne devriez avoir qu'une exportation par défaut. Votre code ci-dessus en a deux.
Lorsque vous rendez le premier votre composant, this.state.name
n'est pas défini, il est donc évalué à undefined
et vous finissez par transmettre value={undefined}
à votre input
.
Lorsque ReactDOM vérifie si un champ est contrôlé, il vérifie si value != null
(notez qu'il s'agit de !=
et non de !==
) et que, depuis undefined == null
en JavaScript, il décide qu'il n'est pas contrôlé.
Ainsi, lorsque onFieldChange()
est appelé, this.state.name
est défini sur une valeur de chaîne, votre entrée passe de non contrôlée à contrôlée.
Si vous faites this.state = {name: ''}
dans votre constructeur, parce que '' != null
, votre entrée aura une valeur tout le temps et ce message disparaîtra.
Une autre approche consiste à définir la valeur par défaut dans votre entrée, comme ceci:
<input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
Je sais que d'autres ont déjà répondu à cela. Mais l’un des facteurs très importants qui peuvent aider d’autres personnes aux prises avec un problème similaire:
Vous devez avoir ajouté le gestionnaire onChange
dans votre champ de saisie (par exemple, textField, case à cocher, radio, etc.). Et toujours gérer l'activité à l'aide du gestionnaire onChange
, comme:
<input ... onChange={ this.myChangeHandler} ... />
et lorsque vous travaillez avec checkbox, vous devrez peut-être gérer son état checked
avec !!
comme:
<input type="checkbox" checked={!!this.state.someValue} onChange={.....} >
Référence: https://github.com/facebook/react/issues/6779#issuecomment-326314716
Un inconvénient potentiel avec la définition de la valeur du champ sur "" (chaîne vide) dans le constructeur est si le champ est un champ facultatif et n'est pas édité. À moins que vous ne fassiez quelques massages avant de poster votre formulaire, le champ sera conservé dans votre stockage de données sous forme de chaîne vide au lieu de NULL.
Cette alternative évitera les chaînes vides:
constructor(props) {
super(props);
this.state = {
name: null
}
}
...
<input name="name" type="text" value={this.state.name || ''}/>
Lorsque vous utilisezonChange={this.onFieldChange('name').bind(this)}
dans votre entrée, vous devez déclarer votre chaîne vide d'état comme valeur du champ de propriété.
manière incorrecte:
this.state ={
fields: {},
errors: {},
disabled : false
}
manière correcte:
this.state ={
fields: {
name:'',
email: '',
message: ''
},
errors: {},
disabled : false
}
Si les accessoires de votre composant ont été passés en tant qu'état, définissez une valeur par défaut pour vos balises d'entrée
<input type="text" placeholder={object.property} value={object.property ? object.property : ""}>
Une mise à jour pour cela. Pour React Hooks, utilisez const [nom, setName] = useState ("")
Définissez une valeur sur la propriété 'name' dans l'état initial.
this.state={ name:''};
Dans mon cas, il me manquait quelque chose de vraiment trivial.
<input value={state.myObject.inputValue} />
Mon état était le suivant quand je recevais l'avertissement:
state = {
myObject: undefined
}
En alternant mon état à référence l'entrée de ma valeur , mon problème a été résolu:
state = {
myObject: {
inputValue: ''
}
}
La solution simple pour résoudre ce problème consiste à définir une valeur vide par défaut:
<input name='myInput' value={this.state.myInput || ''} onChange={this.handleChange} />
Cela se produit généralement uniquement lorsque vous ne contrôlez pas la valeur du fichier lorsque l'application a démarré et après qu'un événement ou une fonction a été déclenché ou que l'état ait changé, vous essayez maintenant de contrôler la valeur dans le champ de saisie.
C’est cette transition qui consiste à ne pas avoir le contrôle de l’entrée, puis à le contrôler.
Le meilleur moyen d'éviter cela est de déclarer une valeur pour l'entrée dans le constructeur du composant. Ainsi, l'élément input a une valeur dès le début de l'application.