Lorsque je clique sur la case à cocher, la coche ne disparaît pas bien que le fichier console.log du gestionnaire onChange indique que l'état a été changé en false. D'autre part, lorsque l'état est modifié par un bouton séparé, la coche bascule correctement.
export default class TestComponent extends Component {
constructor(props) {
super(props);
this.state = {
is_checked: true
};
this.updateCheckbox = this.updateCheckbox.bind(this);
this.pressButton = this.pressButton.bind(this);
}
updateCheckbox(event) {
event.preventDefault();
this.setState({is_checked: !this.state.is_checked});
console.log(this.state.is_checked); // This logs 'false' meaning the click did cause the state change
console.log(event.target.checked); // However, this logs 'true' because the checkmark is still there
}
pressButton(event){
event.preventDefault();
this.setState({is_checked: !this.state.is_checked});
}
render(){
return (
<input type="checkbox" onChange={this.updateCheckbox} checked={this.state.is_checked} ></input>
<button onClick={this.pressButton}>change checkbox state using button</button>
);
}
}
Je pense que je vois ce qui se passe.
Vous cliquez sur le bouton, et il bascule is_checked
, qui coche ou décoche la case. Mais cela finit par déclencher une onChange
pour la case à cocher, ce qui bascule également l'état ... Vous avez en fait codé une boucle infinie. Bien que, depuis les opérations React batch/debounces setState
, votre code ne verrouille pas votre page.
Essaye ça:
var React = require("react");
var Component = React.createClass({
getInitialState: function() {
return {
isChecked: true
};
},
handleCheckboxChange: function(event) {
console.log("checkbox changed!", event);
this.setState({isChecked: event.target.checked});
},
toggleIsChecked: function() {
console.log("toggling isChecked value!");
this.setState({isChecked: !this.state.isChecked});
},
handleButtonClick: function(event) {
console.log("button was pressed!", event);
this.toggleIsChecked();
},
render: function() {
return (
<div>
<input type="checkbox" onChange={this.handleCheckboxChange} checked={this.state.isChecked} />
<button onClick={this.handleButtonClick}>change checkbox state using this button</button>
</div>
);
}
});
module.exports = Component;
Notez que vous pouvez rendre ce code encore plus propre en utilisant valueLink de React (pour en savoir plus: https://facebook.github.io/react/docs/two-way-binding-helpers.html )
La raison de ce comportement est liée à un détail d'implémentation de React - plus précisément à la façon dont React normalise la gestion des modifications dans plusieurs navigateurs. Avec les entrées radio et case à cocher, React utilise un événement de clic à la place d'un événement de modification. Lorsque vous appliquez preventDefault
au sein d'un gestionnaire d'événements attaché, le navigateur ne peut plus mettre à jour visuellement l'entrée radio/case à cocher. Il existe deux solutions possibles:
stopPropagation
alternativementsetTimeout
: setTimeout(x => this.setState(x), 0, {is_checked: !this.state.is_checked});
De préférence, vous n'utilisez pas preventDefault
du tout, sauf si cela est absolument nécessaire.
Regardez cette question React Github pour plus d’informations.
Gardez à l'esprit que setState est asynchrone, donc:
console.log(event.target.checked);
ne doit pas refléter les changements immédiatement. Ma façon de gérer plusieurs champs de case à cocher:
toggleCheckbox(name, event) {
let obj = {};
obj[name] = !this.state[name];
this.setState(obj);
}
Les champs:
<input type="checkbox" name="active" value={this.state.active} checked={this.state.active} onChange={this.toggleCheckbox.bind(this, 'active')} />
<input type="checkbox" name="qtype" value={this.state.qtype} checked={this.state.qtype} onChange={this.toggleCheckbox.bind(this, 'qtype')} />
Le code a été modifié conformément à la documentation React sur la liaison bidirectionnelle pour laquelle Kabir a fourni le lien.
Pour que cela fonctionne je devais
utilisez "React.createClass" au lieu de "extend Component" afin d'utiliser LinkedStateMixin
import react from 'react/addons'
var TestComponent = React.createClass({
mixins: [React.addons.LinkedStateMixin],
render: function(){ ....
remove onChange = 'updateCheckbox' et utilisez this.linkState à la place.
<input type="checkbox" checkedLink={this.linkState(this.state.is_checked)} ></input>