React在状态更改时丢弃排队的事件
Does React discard queued events on state change?
我正在制作一个带有简单验证的React表单组件。每个字段都在模糊上进行验证,并且表单具有一个简单的onSubmit
函数。布尔值存储在字段是否应显示错误消息的状态中,并在验证期间更新。
除了同时触发字段的onBlur
和表单的`onSubmit之外,其他一切都很好。即,我在字段中键入一些内容,然后立即单击提交按钮。
首先执行onBlur
,如果验证状态没有变化,则按预期执行onSubmit
。但是,如果onBlur
更改状态,则onSubmit
函数永远不会被调用。
所以我的问题是;在组件中设置状态是否会清除任何排队的事件?对此问题有任何可能的解决方案吗?
这是我代码的简化版本:
class SimpleForm extends React.Component {
constructor(props) {
super(props);
this.handleBlur = this.handleBlur.bind(this);
this.state = { shouldShowError: false }
}
handleBlur(event) {
console.log("blur")
const isEmpty = event.target.value === ""
this.setState({ shouldShowError: isEmpty })
}
handleSubmit(event) {
event.preventDefault()
console.log("submit")
}
render() {
return (
< form onSubmit = { this.handleSubmit} >
< input type = "text" onBlur = { this.handleBlur } />
{ this.state.shouldShowError ? < p > This field is required. < /p> : null }
< button type = "submit" > Submit < /button >
< /form>
)
}
};
ReactDOM.render(< SimpleForm / >, document.getElementById('container'));
还有一个JSFiddle,它应该让你自己看到错误。任何帮助我们都将不胜感激。
感谢Manolo证实了我的怀疑,即是状态更改擦除了事件队列。我想我已经找到了一个解决方案:
如果你同时需要onBlur和onSubmit主体来执行,你可以将onBlur主体包装在setTimeout中,这样它就会被放在任务队列中,并在onSubmit:之后执行
handleBlur(event) {
const value = event.target.value
setTimeout(() => {
console.log("blur")
const isEmpty = value === ""
this.setState({ shouldShowError: isEmpty })
}, 10)
}
请注意,在react中,默认情况下不能异步访问事件,因此需要提取超时之外所需的值,或者调用event.persist().
我不需要onBlur主体来执行,因为我的onSubmit也会验证表单。经过一点阅读,我发现你可以调用event.relatedTarget来访问焦点转移到的组件。所以我可以检查它是否是提交按钮,如果不是,只执行onBlur主体:
handleBlur(event) {
if (!event.relatedTarget || event.relatedTarget.id !== 'submit') {
console.log("blur")
const isEmpty = event.target.value === ""
this.setState({ shouldShowError: isEmpty })
}
}
是的,更改组件中的状态会清除任何排队的事件,因为状态更改会导致整个组件被重新渲染,并且事件会被清除并重新附加。
我会在提交事件回调中进行验证,而不是模糊验证。若要在用户输入时进行验证,可以使用onKeyUp
。
如果你想保留你的示例行为,你可以在出现错误并且没有错误时在onBlur
回调中提交表单:
class SimpleForm extends React.Component {
constructor(props) {
super(props);
this.handleBlur = this.handleBlur.bind(this);
this.state = { shouldShowError: false }
}
handleBlur(event) {
console.log("blur")
const isShowingError = this.state.shouldShowError;
const isEmpty = event.target.value === ""
if (isShowingError && !isEmpty) {
console.log("submit the form");
}
this.setState({ shouldShowError: isEmpty })
}
handleSubmit(event) {
event.preventDefault()
console.log("submit")
}
render() {
return (
< form onSubmit = { this.handleSubmit} >
< input type = "text" onBlur = { this.handleBlur } />
{ this.state.shouldShowError ? < p > This field is required. < /p> : null }
< button type = "submit" > Submit < /button >
< /form>
)
}
};
ReactDOM.render(< SimpleForm / >, document.getElementById('container'));
https://jsfiddle.net/2r9ua1n1/3/
- 分派点击事件并保留击键修饰符
- 模糊事件的Javascript测试
- keyup事件处理程序更改焦点不适用于快速键入
- 使用 jQuery 的 .on 函数如何获取事件的原始元素
- 如何使Javascript动态html表及其上的事件
- 使用类从一个标记中双击事件
- 如何在未直接触发的情况下停止事件
- 以PubSub/Observer模式对事件进行排队
- 有没有一种方法可以将我的JS函数排队到JSF事件队列中
- HTML Javascript 事件已排队
- React在状态更改时丢弃排队的事件
- 防止事件处理程序排队
- 如何使用 Move.js 防止排队或禁用点击事件
- 事件未正确排队
- Backbone.js:如何将挂起的同步事件排队到服务器
- 如何防止启动排队的事件回调
- 我如何在Javascript循环中排队事件
- jQuery取消先前排队的事件处理程序来重新启动CSS动画
- 如何阻止单击事件在多次单击时排队
- 排队等待旧的单击事件值