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

Posted

技术标签:

【中文标题】反应复选框:event.preventDefault() 中断 onChange 函数 - 为啥?【英文标题】:react checkbox: event.preventDefault() breaks onChange function - why?反应复选框:event.preventDefault() 中断 onChange 函数 - 为什么? 【发布时间】:2021-12-29 12:23:11 【问题描述】:

我刚刚发现了一个流浪的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;

产生的行为是第一次点击时正确更新的状态,但复选框仅在下一个重新呈现时更改为“已检查”外观,例如。第二次点击。

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

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

感谢您的大胆猜测,但这并没有什么不同。参考文献MDN:“调用 preventDefault() during any stage of event flow 会取消事件,这意味着不会发生通常由实现作为事件结果而采取的任何默认操作。”【参考方案2】:

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

检查属性

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

原生 eventListener&lt;input type="checkbox" /&gt;

此外,在不偏离轨道的情况下,本机更改复选框输入状态的事件实际上是 click 事件,而不是 change 事件。如果您在浏览器的 js 控制台中弄乱了侦听器和复选框输入的值,您会看到您可以以不选中复选框的方式对其进行操作,但节点的值另有说明。

可能的解决方案

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

【讨论】:

谢谢你,戴夫。 checked 属性仅描述页面加载时的 default 状态这一事实是一个很好的线索。我仍然无法理解实际行为(在 second 点击时更新外观 - 请参阅上面的Codepen example),但我想其原因深埋在 react 的接口中和浏览器事件。也许一块石头最好不动声色。 ;)

以上是关于反应复选框:event.preventDefault() 中断 onChange 函数 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章

反应复选框。切换复选框时状态迟到

反应复选框不更新

反应复选框不切换

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

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

反应,为啥标签不为复选框触发 onChange?