反应复选框不发送 onChange

Posted

技术标签:

【中文标题】反应复选框不发送 onChange【英文标题】:React Checkbox not sending onChange 【发布时间】:2014-12-24 07:08:01 【问题描述】:

TLDR:使用 defaultChecked 而不是选中,工作 jsbin。

尝试设置一个简单的复选框,当它被选中时会划掉它的标签文本。由于某种原因,当我使用该组件时,handleChange 没有被触发。谁能解释我做错了什么?

var CrossoutCheckbox = React.createClass(
  getInitialState: function () 
    return 
        complete: (!!this.props.complete) || false
      ;
  ,
  handleChange: function()
    console.log('handleChange', this.refs.complete.checked); // Never gets logged
    this.setState(
      complete: this.refs.complete.checked
    );
  ,
  render: function()
    var labelStyle=
      'text-decoration': this.state.complete?'line-through':''
    ;
    return (
      <span>
        <label style=labelStyle>
          <input
            type="checkbox"
            checked=this.state.complete
            ref="complete"
            onChange=this.handleChange
          />
          this.props.text
        </label>
      </span>
    );
  
);

用法:

React.renderComponent(CrossoutCheckbox(text: "Text Text", complete: false), mountNode);

解决方案:

使用 checked 不会让底层值发生变化(显然),因此不会调用 onChange 处理程序。切换到 defaultChecked 似乎可以解决这个问题:

var CrossoutCheckbox = React.createClass(
  getInitialState: function () 
    return 
        complete: (!!this.props.complete) || false
      ;
  ,
  handleChange: function()
    this.setState(
      complete: !this.state.complete
    );
  ,
  render: function()
    var labelStyle=
      'text-decoration': this.state.complete?'line-through':''
    ;
    return (
      <span>
        <label style=labelStyle>
          <input
            type="checkbox"
            defaultChecked=this.state.complete
            ref="complete"
            onChange=this.handleChange
          />
          this.props.text
        </label>
      </span>
    );
  
);

【问题讨论】:

首先,为什么不添加一个只执行this.setState(checked: !this.state.checked) 的onChange 比必须存储一个值更容易。然后检查属性中的三元运算符:checked=this.state.checked ? 'checked': null 这就是它开始的方式,但它似乎从未更新。所以我开始到处弄乱它来调试没有被解雇的东西。理想情况下,完成后会回到最简单的形式:) 假设你的 mountNode 是一个实际的 dom 节点,你必须使用this.refs.complete.getDOMNode().checked。见小提琴jsfiddle.net/d10xyqu1 他可以只使用状态而不是获取 dom 节点:jsfiddle.net/d10xyqu1/1 它工作正常,你一定打错了。 忽略 TLDR 注释 - defaultChecked 并不总是答案 【参考方案1】:

要获得复选框的选中状态,路径将是:

this.refs.complete.state.checked

另一种方法是从传递给handleChange方法的事件中获取它:

event.target.checked

【讨论】:

handleChange 永远不会被调用,无论您单击复选框还是标签,handleChange 都不会被调用:(. 尝试在您的输入中使用 defaultChecked=this.state.complete 而不是“checked”。 就是这样......一直在寻找和四处寻找。如果其他人也遇到此问题,将使用完整的工作答案更新问题。 但是为什么 - 有同样的问题,但你应该使用 checked 控制组件:/ 设置checked 表示状态在组件外部进行管理。当用户点击时,没有什么可以调用handleChange,因为没有更新状态。相反,您需要监听 onClick 并在那里触发状态更新。【参考方案2】:

在这种情况下最好不要使用 refs。使用:

<input
    type="checkbox"
    checked=this.state.active
    onClick=this.handleClick
/>

有一些选择:

checkeddefaultChecked

前者会同时响应状态变化点击。 后者会忽略状态变化。

onClickonChange

前者总是会在点击时触发。 如果checked 属性存在于input 元素上,则后者不会在点击时触发。

【讨论】:

我正在使用 React 16.13.1,如果没有 onChange 属性,您将无法提供选中的属性。如果我同时定义两者,并使选中的属性响应输入,那么每次单击该框时我都会获得所需的行为和 onChange 触发器。所以我认为这个答案已经过时了。【参考方案3】:

如果您有一个如下所示的handleChange 函数:

handleChange = (e) => 
  this.setState(
    [e.target.name]: e.target.value,
  );

您可以创建一个自定义的onChange 函数,使其像文本输入一样工作:

<input
  type="checkbox"
  name="check"
  checked=this.state.check
  onChange=(e) => 
    this.handleChange(
      target: 
        name: e.target.name,
        value: e.target.checked,
      ,
    );
  
/>

【讨论】:

不是handleChange on input 应该是this.handleChange 你犯了一个小错误 -> [e.target.name]: e.target.checked @Haikel 如果您有一个仅处理复选框输入的 handleChange 函数,那将是正确的,但是如果您注意到在第二个代码块中我们在箭头函数中调用 handleChange 并且将target.value 设置为e.target.checked(本质上是创建一个虚假事件)。这样做是为了使相同的 handleChange 函数也可以用于文本输入,因为这就是它们在更改事件中传递值的方式。【参考方案4】:

在您不想在输入 DOM 上使用 onChange 处理程序的场景中,您可以使用 onClick 属性作为替代方案。 defaultChecked,条件可能会为 v16 IINM 留下固定状态。

 class CrossOutCheckbox extends Component 
      constructor(init)
          super(init);
          this.handleChange = this.handleChange.bind(this);
      
      handleChange(target)
          if (target.checked)
             target.removeAttribute('checked');
             target.parentNode.style.textDecoration = "";
           else 
             target.setAttribute('checked', true);
             target.parentNode.style.textDecoration = "line-through";
          
      
      render()
         return (
            <span>
              <label style=textDecoration: this.props.complete?"line-through":"">
                 <input type="checkbox"
                        onClick=this.handleChange
                        defaultChecked=this.props.complete
                  />
              </label>
                this.props.text
            </span>
        )
    
 

我希望这对将来的某人有所帮助。

【讨论】:

【参考方案5】:

如果有人正在寻找通用事件处理程序,可以或多或少地使用以下代码(假设为每个输入设置了 name 属性):

    this.handleInputChange = (e) => 
        item[e.target.name] = e.target.type === "checkbox" ? e.target.checked : e.target.value;
    

【讨论】:

【参考方案6】:

使用 defaultChecked 时,onChange 不会在移动设备上调用 handleChange。作为替代方案,您可以使用 onClick 和 onTouchEnd。

<input onClick=this.handleChange onTouchEnd=this.handleChange type="checkbox" defaultChecked=!!this.state.complete />;

【讨论】:

【参考方案7】:

在material ui中,checkbox的状态可以取为

this.refs.complete.state.switched

【讨论】:

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

反应复选框:event.preventDefault() 中断 onChange 函数 - 为啥?

反应复选框不切换

如何为javascript复选框提供onchange事件?

将复选框值推送到状态 onChange 的数组

反应复选框组/单个复选框

复选框 onchange 触发两次