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

react checkbox: event.preventDefault() breaks onChange function - why?

我刚刚发现一个杂乱的 event.preventDefault() 破坏了我的复选框的 onChange 处理程序:

import { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      accepted: false
    }
  }

  changeChecked = (event) => {
    this.setState((state) => ({
      accepted : !state.accepted
    }));
    event.preventDefault(); // <- this very bad
  }

  render() {
    return (
      <input
        type="checkbox" 
        onChange={this.changeChecked}
        checked={this.state.accepted}
      />
    );
  }
}

export default App;

由此产生的行为是在第一次点击时正确更新状态,但复选框只会在 next 重新呈现时更改为它的 'checked' 外观,例如。第二次点击。

这是为什么?受控组件独立于浏览器事件工作不是重点吗?

如果有人向我解释这一点,肯定会减轻我花费数小时简化复杂用例的痛苦。谢谢!

更新:这是一个快速的Codepen example演示奇怪的行为。 我包括了一个 'unprevented checkbox' 和一个带有阻止的 onClick 事件作为比较。 请注意,当我单击 different 复选框时,带有 prevented onChange 的那个如何将其外观切换到实际状态。

尝试将 event.preventDefault() 移动到 this.setState 行上方。

复选框的行为略有不同。您可能知道,preventDefault() 的典型用例是表单的 onSubmit() 函数,您将在其中执行自己的 AJAX 调用,因此希望阻止默认表单提交。但是对于复选框(以及大多数输入),涉及的内容更多一些。

选中的属性

根据 MDNchecked 属性是“一个布尔属性,指示默认情况下是否选中此复选框(当页面加载时)。它 指示此复选框当前是否已选中:如果复选框的状态发生更改,则此内容属性不会反映更改。”有趣的是,checked 属性与是否检查输入状态之间存在脱节。对于 React,在每次重新渲染时,checked 属性将反映当前状态,但它仍然只是一个默认值,因为输入是新渲染的,并且自上次状态更改后未被操作。

原生 eventListener <input type="checkbox" />

此外,在不偏离轨道的情况下,本机更改复选框输入状态的事件实际上是 click 事件,而不是 change 事件。如果你在浏览器的 js 控制台中弄乱了监听器和复选框输入的值,你会发现你可以以一种不选中复选框的方式来操作它,但节点的值却另有说明。

可能的解决方案

基于上述,在这种情况下,您不想阻止默认行为,因为change事件的默认行为不冲突与你想做的事情(并且出于某种原因阻止它会导致问题)。事实上,在 React docs examples 中,您会注意到它们在更新受控组件的状态时不使用 preventDefault()。我希望我能更好地理解 究竟为什么 添加 preventDefault() 来更改输入的处理程序会导致这样的问题,但希望这几个小花絮能让人更加清楚。