反应复选框: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 调用,因此希望阻止默认表单提交。但是对于复选框(以及大多数输入),涉及的内容更多一些。
选中的属性
根据 MDN,checked
属性是“一个布尔属性,指示默认情况下是否选中此复选框(当页面加载时)。它不 指示此复选框当前是否已选中:如果复选框的状态发生更改,则此内容属性不会反映更改。”有趣的是,checked
属性与是否检查输入状态之间存在脱节。对于 React,在每次重新渲染时,checked
属性将反映当前状态,但它仍然只是一个默认值,因为输入是新渲染的,并且自上次状态更改后未被操作。
原生 eventListener
<input type="checkbox" />
此外,在不偏离轨道的情况下,本机更改复选框输入状态的事件实际上是 click
事件,而不是 change
事件。如果你在浏览器的 js 控制台中弄乱了监听器和复选框输入的值,你会发现你可以以一种不选中复选框的方式来操作它,但节点的值却另有说明。
可能的解决方案
基于上述,在这种情况下,您不想阻止默认行为,因为change
事件的默认行为不冲突与你想做的事情(并且出于某种原因阻止它会导致问题)。事实上,在 React docs examples 中,您会注意到它们在更新受控组件的状态时不使用 preventDefault()
。我希望我能更好地理解 究竟为什么 添加 preventDefault()
来更改输入的处理程序会导致这样的问题,但希望这几个小花絮能让人更加清楚。
我刚刚发现一个杂乱的 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 调用,因此希望阻止默认表单提交。但是对于复选框(以及大多数输入),涉及的内容更多一些。
选中的属性
根据 MDN,checked
属性是“一个布尔属性,指示默认情况下是否选中此复选框(当页面加载时)。它不 指示此复选框当前是否已选中:如果复选框的状态发生更改,则此内容属性不会反映更改。”有趣的是,checked
属性与是否检查输入状态之间存在脱节。对于 React,在每次重新渲染时,checked
属性将反映当前状态,但它仍然只是一个默认值,因为输入是新渲染的,并且自上次状态更改后未被操作。
原生 eventListener
<input type="checkbox" />
此外,在不偏离轨道的情况下,本机更改复选框输入状态的事件实际上是 click
事件,而不是 change
事件。如果你在浏览器的 js 控制台中弄乱了监听器和复选框输入的值,你会发现你可以以一种不选中复选框的方式来操作它,但节点的值却另有说明。
可能的解决方案
基于上述,在这种情况下,您不想阻止默认行为,因为change
事件的默认行为不冲突与你想做的事情(并且出于某种原因阻止它会导致问题)。事实上,在 React docs examples 中,您会注意到它们在更新受控组件的状态时不使用 preventDefault()
。我希望我能更好地理解 究竟为什么 添加 preventDefault()
来更改输入的处理程序会导致这样的问题,但希望这几个小花絮能让人更加清楚。