react div 容器 onClick 与复选框 onChange 冲突

IT技术 reactjs
2021-05-09 11:10:09

在下面的 React 类中,我在 div 容器中有一个复选框。我想点击容器来切换复选框。我还认为我需要绑定复选框输入本身的 onChange,以处理诸如当用户使用 Tab/spacing 来切换复选框的状态之类的事情(如果我没有指定 onChange,我也会收到来自 React 的警告,因为这是一个受控组件)。

我的问题是当我单击复选框本身时两个事件处理程序都会触发,因此复选框的状态实际上并没有改变。我在 handleCheckboxChange 中尝试过 e.preventDefault 和 e.stopPropagation 但似乎都没有做任何事情。

export default class Item extends React.Component{
    constructor(){
        super();
        this.state={
            IsSelected: false
        }
    }
    render(){
        return (
            <div className="item">
                <div className="checkbox-container" onClick={this.handleContainerClick.bind(this)}>
                    <input type="checkbox" checked={this.state.IsSelected} onChange={this.handleCheckboxChange.bind(this)} />
                </div>                  
            </div>
        );
    }
    handleCheckboxChange(e){
        this.setState({
            IsSelected: !this.state.IsSelected
        });
    }
    handleContainerClick(){
        this.setState({
            IsSelected: !this.state.IsSelected
        });     }
}
1个回答

如果您希望包含<div>在复选框值的“控制”中,则不要在复选框本身上放置任何处理程序。React 将确保容器将接收 childsclick事件。

var CheckboxInClickableBox = React.createClass({
  getInitialState: function () {
    return {
      checked: false
    };
  },
  render: function () {
    return (
      <div onClick={this.onClick}>
        <span>{"Checked: " + this.state.checked}</span>

        <br />

        <input type="checkbox" checked={this.state.checked} />
      </div>
    );
  },
  onClick: function () {
    this.setState({
      checked: !this.state.checked
    });
  }
});

JSBin 示例- 单击绿色框中的任意位置将触发切换。

此外,HTML 规定<label>带有for="pie"属性的a会将click事件传递给任何<input id="pie">. 使用上述方法时,这似乎会“破坏”您的复选框 - 例如:

  render: function () {
    return (
      <div onClick={this.onClick}>
        <label htmlFor="pie">{"Checked: " + this.state.checked}</label>

        <br />

        <input id="pie" type="checkbox" checked={this.state.checked} />
      </div>
    );
  }

单击<label>将表现得好像有 2 个单击事件:

  • 第一个是click<label>的原始事件冒泡<div>并触发我们的onClick处理程序
  • 第二个是<label>“委托”它的点击到<input>元素,由于for属性(htmlFor在 React 中),然后冒泡并击中我们的onClick处理程序

JSBin 示例- 单击框中的任意位置,除了<label>将触发切换。单击<label>将触发 2 个切换。