J'ai un problème très ennuyant avec React et les cases à cocher. L'application avec laquelle je travaille nécessite une liste de cases à cocher représentant les paramètres conservés dans le back-end. Il existe une option pour restaurer les paramètres à leur état d'origine .
Au début, j'ai créé un composant qui a un objet comme une carte de paramètres. Chaque paramètre a une clé et une valeur booléenne. Par conséquent:
{
bubbles: true,
gregory: false
}
Doit être représenté comme:
<input type="checkbox" value="bubbles" checked="checked" />
<input type="checkbox" value="gregory" />
Il semble maintenant que React ignore comment une case à cocher est censée fonctionner. Je ne veux pas définir les valeurs des cases à cocher, je veux la propriété "cochée".
Pourtant, si j'essaie quelque chose comme ça:
<input
type="checkbox"
value={setting}
checked={this.settings[setting]}
onChange={this.onChangeAction.bind(this)}
/>
Je reçois cet avertissement:
Avertissement: AwesomeComponent modifie une case à cocher de type non contrôlée à contrôler. Les éléments d'entrée ne doivent pas basculer de non contrôlés à contrôlés (ou vice versa). Choisissez d'utiliser un élément d'entrée contrôlé ou non contrôlé pour la durée de vie du composant. Plus d'infos: [des pages de documentation inutiles que j'ai lues plusieurs fois sans résultat]
J'ai donc décidé de créer un autre composant pour envelopper chaque case et j'ai obtenu ceci:
<input
type="checkbox"
checked={this.state.checked}
onChange={this.onChangeAction.bind(this)}
/>
Maintenant, la checked
est une propriété présente directement dans mon état.
Cela donne le même avertissement, alors j'ai essayé d'utiliser defaultChecked
:
<input
type="checkbox"
defaultChecked={this.state.checked}
onChange={this.onChangeAction.bind(this)}
/>
Cela fait disparaître l'avertissement, mais il est maintenant impossible de réinitialiser la valeur checked
à celle par défaut. J'ai donc essayé de jouer avec la méthode componentWillReceiveProps
. De cette façon, je suis presque sûr que mon état est correct, this.state.checked
est correct et le composant est à nouveau rendu.
Et ça le fait. Mais la case à cocher reste telle qu’elle était à l’origine ... Pour l’instant, j’ai laissé cet avertissement déplorable et j’utilise checked
.
Je pensais qu'il existait peut-être un moyen de forcer le nouveau rendu du composant, de sorte qu'il capture la nouvelle valeur defaultChecked
et l'utilise. Mais je ne sais pas comment faire ça. Peut-être supprimer l'avertissement seulement pour ce composant? Est-ce possible? Peut-être y a-t-il autre chose à faire?
Le problème se pose si vous définissez la propriété checked
de votre case à cocher sur null
ou undefined
.
Ce sont des valeurs "faussement" dans JS, cependant React traite une valeur de null
comme si la propriété n'était pas définie du tout. Étant donné que l'état par défaut d'une case à cocher est désactivé, tout fonctionnera correctement. Si vous définissez ensuite checked
sur true
React pense que la propriété est soudainement créée! C'est à ce moment que React estime que vous êtes passé de non contrôlé à contrôlé, puisque la propriété checked
existe.
Dans votre exemple, vous pouvez supprimer cet avertissement en remplaçant checked={this.settings[setting]}
par checked={!!this.settings[setting]}
. Notez le double coup (!!
). Ils vont convertir null
ou undefined
en false
(et laisser true
seul), donc React enregistrera votre propriété checked
avec une valeur de false
et démarrera avec un composant de formulaire contrôlé.
J'ai eu ce problème aussi et j'ai aussi lu les docs sur les composants contrôlés plusieurs fois sans succès, mais j'ai finalement compris, alors j'ai pensé partager. De plus, depuis version 15.2.0 , les entrées normales sont déclenchées en définissant value
, tandis que les cases à cocher sont initialisées de la manière contrôlée en définissant checked
, quelle que soit leur propriété value
, ce qui ajoute un peu à la confusion.
La réponse d'Amoebe est correcte, mais je pense qu'il existe une solution plus propre que la double banque (!!
). Ajoutez simplement un defaultProps property avec la valeur false
pour checked
prop de votre composant Checkbox:
import React from 'react';
const Checkbox = ({checked}) => (
<div>
<input type="checkbox" checked={checked} />
</div>
);
Checkbox.defaultProps = {
checked: false
};
export default Checkbox;
Fondamentalement, la variable defaultChecked
signifie que vous ne voulez pas contrôler l'entrée - elle restitue avec cette valeur et il n'y a aucun moyen de la contrôler. De plus, value
ne devrait pas être utilisé, mais plutôt checked
, votre deuxième code devrait donc être correct. Et vous ne devriez pas les utiliser simultanément.
<input
type="checkbox"
checked={this.state.checked}
onChange={this.onChangeAction.bind(this)}
/>
Pouvez-vous créer un petit violon avec ce comportement?
Vous pouvez affecter vos données à l'état, puis utiliser la propriété cochée associée à la case à cocher individuelle pour définir l'état comme
{ this.state.data.map(function(item, index) {
return (
<input type="checkbox" checked={item.value} onChange={this.handleChange.bind(this, index)}/>
);
}.bind(this))
}
Exemple de données dans l'état est comme
data: [{name:'bubbles', value: true}, {name:'gregory', value: false}]