反应复选框不切换

Posted

技术标签:

【中文标题】反应复选框不切换【英文标题】: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>
    );


【问题讨论】:

我知道已经有一段时间了,但接受的答案在某种程度上具有误导性(虽然没有错)。此外,我认为您不应该像在自己的答案中那样使用双向绑定来解决此问题。 【参考方案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 文档更改了代码。

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

    使用“React.createClass”而不是“扩展组件”来使用 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> 
    

【讨论】:

【参考方案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') />

【讨论】:

以上是关于反应复选框不切换的主要内容,如果未能解决你的问题,请参考以下文章

反应复选框不更新

Angular 反应复选框仅在第一次单击后正确切换

未选中特定复选框时,反应切换选择字段未删除

点击时复选框 UIButton 标题不切换

反应,为啥标签不为复选框触发 onChange?

反应复选框不发送 onChange