当我单击该复选框时,虽然onChange处理程序中的console.log指示状态已更改为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>
);
}
}
答案 0 :(得分:25)
我想我知道发生了什么。
您点击该按钮,然后切换is_checked
,它会选中或取消选中此框。但最终会触发onChange
复选框,这也会切换状态......你实际上编码了一个无限循环。虽然,由于React批量/去抖setState
操作,您的代码不会锁定您的页面。
试试这个:
2019更新hooks API:
import React, { useState } from 'react';
const Component = () => {
const [isChecked, setIsChecked] = useState(true);
return (
<div>
<input
type="checkbox"
onChange={(event) => setIsChecked(event.currentTarget.checked)}
checked={isChecked}
/>
<button onClick={() => setIsChecked(!isChecked)}>
change checkbox state using this button
</button>
</div>
);
};
原件:
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)
答案 1 :(得分:13)
此行为的原因与React的实现细节有关 - 更具体地说,React如何规范化跨浏览器的更改处理。通过无线电和复选框输入,React使用click事件代替change事件。在附加的事件处理程序中应用preventDefault
时,这会阻止浏览器直观地更新radio / checkbox输入。有两种可能的解决方法:
stopPropagation
setTimeout
:setTimeout(x => this.setState(x), 0, {is_checked: !this.state.is_checked});
除非绝对必要,否则您最好不要使用preventDefault
。
请查看此React Github issue以获取更多信息。
答案 2 :(得分:1)
请记住,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')} />
答案 3 :(得分:0)
根据Kabir为其提供链接的双向绑定的React文档更改了代码。
要使它工作,我必须
使用&#34; React.createClass&#34;而不是&#34;扩展组件&#34;为了使用LinkedStateMixin
import react from 'react/addons'
var TestComponent = React.createClass({
mixins: [React.addons.LinkedStateMixin],
render: function(){ ....
删除onChange =&#39; updateCheckbox&#39;并改用this.linkState。
<input type="checkbox" checkedLink={this.linkState(this.state.is_checked)} ></input>