React setState异步特性下,按钮点击能否在禁用前触发两次?
问题:React setState异步特性下快速点击上传按钮是否会触发两次onClick?
嘿,这个场景绝对是有可能发生的,核心原因就是React setState的异步批量更新机制——状态更新不是即时生效的,这就给快速点击留下了可乘之机。
为什么会出现这种情况?
当你第一次点击按钮调用upload方法时,this.setState({ uploadDisabled: true })并不会立刻把组件的uploadDisabled状态改成true。React会把这次状态更新放进一个队列,等当前的事件循环(也就是这次点击的回调执行完)结束后,才会统一处理队列里的状态更新,再重新渲染组件。
这就意味着,在第一次点击后的几十毫秒内,按钮的disabled属性依然是基于旧状态false渲染的,按钮还是可点击的。如果这时候你快速点击第二次,upload方法会被再次调用,/upload请求也会被发送第二次——直到React完成状态更新,按钮才会真正被禁用。
复现方法
- 把你提供的代码放到本地React项目或者在线编辑器(比如CodeSandbox)中运行
- 打开浏览器的Network面板,方便观察请求数量
- 用最快的速度连续点击Upload按钮2次以上(手动快速点击就行,要是手速不够,也可以写个简单的自动点击脚本,比如在控制台执行
setInterval(() => document.querySelector('button').click(), 10),不过注意要及时停止) - 你会看到Network面板里出现多个
/upload请求,这就说明upload方法被触发了多次
你的代码示例
import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component { constructor (props) { super(props) this.state = { uploadDisabled: false } } upload = () => { this.setState({ uploadDisabled: true }) fetch('/upload').then(() => { this.setState({ uploadDisabled: false }) }) } render () { return ( <div> <button disabled={this.state.uploadDisabled} onClick={this.upload}> Upload </button> </div> ) } }
内容的提问来源于stack exchange,提问作者Transcendence
相关产品推荐
相关产品推荐

