Флажок "Реакция" не переключается
Когда я нажимаю флажок, галочка не исчезает, хотя console.log в обработчике onChange указывает, что состояние изменено на false. С другой стороны, когда состояние изменяется отдельной кнопкой, галочка правильно включает и выключает.
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>
);
}
}
Ответы
Ответ 1
Я думаю, что вижу, что происходит.
Вы нажимаете кнопку, и она переключает is_checked
, которая либо проверяет, либо снимает флажок. Но это заканчивает запуск onChange
для флажка, который также переключает состояние... Фактически вы закодировали бесконечный цикл. Хотя, поскольку React выполняет пакетные операции /debounces setState
, ваш код не будет блокировать вашу страницу вверх.
Попробуйте следующее:
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;
Обратите внимание, что вы можете сделать этот код еще более чистым, используя React valueLink (подробнее здесь: https://facebook.github.io/react/docs/two-way-binding-helpers.html)
Ответ 2
Причина такого поведения связана с детализацией реализации React, а именно тем, как React нормализует обработку кросс-браузера. При использовании радио и флажков React использует событие click вместо события изменения. Когда вы применяете preventDefault
в подключенном обработчике событий, это останавливает браузер от визуального обновления ввода радио/флажка. Возможны два способа обхода:
- используйте
stopPropagation
альтернативно
- установите переключатель в
setTimeout
: setTimeout(x => this.setState(x), 0, {is_checked: !this.state.is_checked});
Предпочтительно, вы не используете preventDefault
вообще, если это абсолютно необходимо.
Посмотрите на этот React Github для получения дополнительной информации.
Ответ 3
Изменен код для документации React по двусторонней привязке, для которой Kabir предоставил ссылку.
Чтобы сделать это, я должен был
-
используйте "React.createClass" вместо "extends Component", чтобы использовать LinkedStateMixin
import react from 'react/addons'
var TestComponent = React.createClass({
mixins: [React.addons.LinkedStateMixin],
render: function(){ ....
-
удалить onChange = 'updateCheckbox' и вместо этого использовать this.linkState.
<input type="checkbox" checkedLink={this.linkState(this.state.is_checked)} ></input>
Ответ 4
Имейте в виду, что setState асинхронен, поэтому:
console.log(event.target.checked);
не будет немедленно отражать изменения. Мой способ обработать несколько полей флажков:
toggleCheckbox(name, event) {
let obj = {};
obj[name] = !this.state[name];
this.setState(obj);
}
Поля:
<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')} />