复选框内部状态覆盖道具

问题描述 投票:0回答:2

我很惊讶复选框功能不是我预期会发生的。如果我有一个带有onClick的包装器div,并点击除复选框之外的任何内容,它会按预期工作。但是,当我单击复选框时,即使传递的propp确实更新,复选框也保持相同的状态。我的猜测是,在推文改变被推下之后,复选框正在触发其内部更新事件。

const ToDo = (props) => {
  const { title, done, onChange } = props;

  const handleChange = (event) => {
    event.preventDefault();
    if (onChange) {
      onChange(!done)
    }
  }

  return (
    <div onClick={handleChange}>
      <label>
        <input type="checkbox" checked={done}/> {title}
      </label>
    </div>
  );
};

我想知道处理这个问题的正确方法是什么?

reactjs react-dom
2个回答
1
投票

似乎正在发生的事情是,当你点击标签时,它会调用复选框的onChange函数以及div的onClick

解决这个问题的一个简单方法是禁用标签上的指针事件,因此只调用onClick(我假设你需要在父节点上使用onClick而不是在输入本身上使用onChange)。

可能有另一种方法可以阻止事件传播,但是你必须处理多个处理程序,所以css方式似乎很简单。

这是一个演示:

class App extends React.Component {
  state = {
    done: false
  }
  
  onCheckDone = (done) => {
    this.setState({
      done
    });
  }
  
  render() {
    return (
      <ToDo
        title="hello"
        done={this.state.done}
        onChange={this.onCheckDone}
      />
    );
  }
}

const ToDo = (props) => {
  const { title, done, onChange } = props;

  const handleChange = (event) => {
    event.stopPropagation();
    if (onChange) {
      onChange(!done)
    }
  }
  
  return (
    <div className="clicker" onClick={handleChange}>
      <label>
        <input type="checkbox" checked={done} /> {title}
      </label>
    </div>
  );
};

ReactDOM.render(
  <App />,
  document.getElementById('app')
);
.clicker {
  border: solid 1px #ccc;
  padding: 10px 20px;
}

label {
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

0
投票

这是我发现的简单易用的工作方式。传递一个不同的密钥key={done}将强制将复选框组件重新渲染为不同的dom项,因此它可以工作,但似乎应该有更好的方法来执行此操作。我知道在使用文本输入时不需要这样做,因为值仍然是prop传递下来的。

const ToDo = (props) => {
  const { title, done, onChange } = props;

  const handleChange = (event) => {
    event.preventDefault();
    if (onChange) {
      onChange(!done)
    }
  }

  return (
    <div onClick={handleChange}>
      <label>
        <input key={done} type="checkbox" checked={done}/> {title}
      </label>
    </div>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.