javascript
this.setState({
num: 2
})
setTimeout(() => {
this.setState({
num: 4
})
}, 2000)
延迟 2 秒后,把组件状态里的 num 更新成 4。
setTimeout(..., 2000):等待 2000ms(2 秒) 后执行里面的函数
this.setState({ num:4 }):React 组件更新状态方法,把 num 设为 4
① 异步执行
setTimeout 是异步任务,不会阻塞代码,2 秒后才会进入任务队列执行。
② React 状态更新是异步的
setState 本身也是异步更新,不会立刻修改 state。
③ this 指向问题(高频坑点)
在 setTimeout 回调里用 this,必须确保 this 指向当前组件实例。
用箭头函数没问题(继承外层 this)
用普通 function 会丢 this,报错
javascript
this.setState({
num: 2
})
this.setState({
num: 4
})
最终 num 只会是 3,不会先变成 2 再变成 3,页面只会渲染一次 3。
这是 React setState 批量更新机制导致的:
连续调用 setState 会被合并在同步代码、合成事件、生命周期里,React 不会每次 setState 都立即更新,而是先把多个更新合并成一次,最后一起执行。
后面的会覆盖前面的
this.setState({ num: 2 })
this.setState({ num: 3 })
这两句是连续同步执行,React 会把它们合并:
先记录要更新 num:2
又记录要更新 num:3
最终只执行最后一次:num=3
页面只会渲染一次,值是 3不会出现 2 → 3 的过程。
javascript
// 初始 this.state.num = 0
this.setState({ num: this.state.num + 1 }) // 第1次
console.log(this.state.num) // 日志1
this.setState({ num: this.state.num + 1 }) // 第2次
console.log(this.state.num) // 日志2
setTimeout(() => {
this.setState({ num: this.state.num + 1 }) // 第3次
console.log(this.state.num) // 日志3
this.setState({ num: this.state.num + 1 }) // 第4次
console.log(this.state.num) // 日志4
}, 0)
控制台输出顺序:
0
0
2
3
最终 state.num = 3
- 前两次 setState(同步批量更新)
js
this.setState({ num: this.state.num + 1 })
this.setState({ num: this.state.num + 1 })
关键点:
setState 是异步的
同步代码里连续 setState 会被合并
合并时,后面的会覆盖前面的
this.state 不会立即更新
所以:
两次 setState 拿到的都是 原始值 0
0+1、0+1 → 最终合并成 num = 1
所以前两个 console.log 输出:
plaintext
0
0 - setTimeout 里的 setState(重点!)
js
setTimeout(() => {
// 此时批量更新已结束,state 已经是 1
this.setState({ num: this.state.num + 1 }) // 1+1=2
console.log(this.state.num) // 2
this.setState({ num: this.state.num + 1 }) // 2+1=3
console.log(this.state.num) // 3
}, 0)
关键点:
setTimeout 里脱离 React 批量更新
setState 会同步更新 state
每次 setState 后 this.state 立即生效
所以:
第一次:1 → 2
第二次:2 → 3
输出:
plaintext
2
3
同步代码里 setState 是异步批量更新,不会立即修改 state,连续调用会被合并,后面覆盖前面。
setTimeout 属于宏任务,会在同步代码执行完才运行。
定时器里的 setState 脱离 React 批量更新,变成同步执行,每次调用都会立即更新 state,后面能拿到前面的值。
所以同步里两次 + 1 最终只变成 1,定时器里两次 + 1 会变成 2、3。