【问题标题】:React checkbox doesn't toggle反应复选框不切换
【发布时间】:2015-12-31 14:43:28
【问题描述】:

当我单击复选框时,尽管 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>
    );
}
}

【问题讨论】:

  • 我知道已经有一段时间了,但接受的答案在某种程度上具有误导性(虽然没有错)。此外,我认为您不应该像在自己的答案中那样使用双向绑定来解决此问题。

标签: checkbox reactjs


【解决方案1】:

我想我明白发生了什么。

您单击该按钮,它会切换is_checked,它会选中或取消选中该框。但这最终会触发复选框的onChange,这也会切换状态......您实际上已经编写了一个无限循环。虽然,由于 React 批处理/去抖动 setState 操作,您的代码不会锁定您的页面。

试试这个:

钩子 API 的 2019 年更新:

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)

【讨论】:

  • 感谢您的帮助。您提供的代码有同样的问题,但双向绑定的链接很有帮助。更新了我的帖子以显示有效的解决方案。
  • 我忘了在handleCheckboxChange 中添加行,它实际上更新了isChecked 状态——秘密是使用event.target.checked 的值。我更新了代码,仅供参考。这也是一个小提琴:jsfiddle.net/xqb2mxsq
  • 您也可以通过删除“event.preventDefault();”来解决这个问题线。因为这会阻止复选框被选中。因此它将始终是相同的状态。
  • 我知道这是旧的,但问题的根源是e.preventDefault()。通过阻止 on chagne 的默认行为,即使调用了事件处理程序,您也可以阻止更改发生。所以换句话说,复选框发生了变化,状态发生了变化,然后复选框取消设置,因为它的行为被阻止了。因此,初始代码只需删除 e.preventDefault()
  • 这对我来说也适用于useReducer。谢谢你。
【解决方案2】:

根据 Kabir 提供的链接的双向绑定的 React 文档更改了代码。

为了让它发挥作用,我不得不

  1. 使用“React.createClass”而不是“扩展组件”来使用 LinkedStateMixin

    import react from 'react/addons'
    
    var TestComponent = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    render: function(){ ....
    
  2. 删除 onChange='updateCheckbox' 并改用 this.linkState。

    <input type="checkbox" checkedLink={this.linkState(this.state.is_checked)} ></input> 
    

【讨论】:

    【解决方案3】:

    这种行为的原因与 React 的实现细节有关——更具体地说,是 React 如何规范化跨浏览器的更改处理的方式。对于单选和复选框输入,React 使用点击事件代替更改事件。当您在附加的事件处理程序中应用 preventDefault 时,这会阻止浏览器以可视方式更新单选框/复选框输入。有两种可能的解决方法:

    • 也可以使用stopPropagation
    • 将开关放入setTimeout:setTimeout(x =&gt; this.setState(x), 0, {is_checked: !this.state.is_checked});

    除非绝对必要,否则最好不要使用preventDefault。

    查看此React Github issue 了解更多信息。

    【讨论】:

    • 摆脱 preventDefualt 为我解决了这个问题,使用 react 15 和 typescript 2.2(抱歉格式错误)toggleMyCheckbox(checkboxExent: React.ChangeEvent) { checkboxExent.preventDefault(); this.setState({ checkboxModel: this.state.checkboxModel, 检查: !this.state.checked }) } to.. toggleMyCheckbox(checkboxExent: React.ChangeEvent) { this.setState({ checkboxModel: this.state. checkboxModel,选中:!this.state.checked }) }
    • 谢谢你,我也摆脱了阻止默认设置,它对我有用。
    • 很好的解释。真的帮助了这个 React 新手。
    • 谢谢,preventDefault() 也是我的问题。
    【解决方案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')} />
    

    【讨论】:

      猜你喜欢
      • 2017-02-27
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 1970-01-01
      相关资源
      最近更新 更多