复选框内部状态覆盖道具

时间:2017-12-17 04:15:53

标签: reactjs react-dom

我很惊讶复选框功能不是我预期的。如果我有一个带有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>
  );
};

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

2 个答案:

答案 0 :(得分:1)

似乎正在发生的事情是,当您点击标签时,它会调用复选框的onChange功能以及div onClick。< / p>

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

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

这是一个演示:

&#13;
&#13;
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')
);
&#13;
.clicker {
  border: solid 1px #ccc;
  padding: 10px 20px;
}

label {
  pointer-events: none;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

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

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>
  );
};