網站首頁 編程語言 正文
函數式組件中的useState
前言:眾所周知useState是異步的,但網絡上對于useState何時異步更新并沒有一個共識,為了探究,做一個簡單的實驗,實驗目的是探究useState與微任務、宏任務的先后關系
測試1
實驗步驟:點擊按鈕觸發事件,在事件中我們做三件事:修改state/定義一個宏任務setTimeout /定義一個微任務promise.then?,我們在微任務中打上debugger,暫停代碼,觀察此時頁面是否更新了數據。
實驗代碼
import React, { useState } from 'react'
export default function Test() {
const [msg, setMsg] = useState('我是初始值')
const onChange = () => {
setMsg('我是更新值')
setTimeout(() => {
console.log('宏任務')
}, 0);
Promise.resolve().then(res=>{
debugger
console.log('微任務')
})
}
return (
<div>
<h2>{msg}</h2>
<button onClick={onChange}>按鈕</button>
</div>
)
}
實驗期望:
- 如果頁面更新了,則說明在微任務之前,useState就已經更新了狀態,并且頁面渲染完畢了
- 如果頁面未更新,則說明微任務在useState更新之前
實驗結果
結果分析 結果符合第一種期望,useState在此微任務之前就完成了,由此得出useState異步更新是在微任務之前,同步代碼之后的結果,這是不準確的。讓我們進一步測試。
測試2
實驗步驟:測試2在廁所1上調整下順序。定義宏任務/定義微任務/修改state
實驗代碼:
import React, { useState } from 'react'
export default function Test() {
const [msg, setMsg] = useState('我是初始值')
const onChange = () => {
setTimeout(() => {
console.log('宏任務')
}, 0);
Promise.resolve().then(res=>{
debugger
console.log('微任務')
})
setMsg('我是更新值')
}
return (
<div>
<h2>{msg}</h2>
<button onClick={onChange}>按鈕</button>
</div>
)
}
實驗期望
- 如果頁面更新了,則說明在微任務之前,useState就已經更新了狀態,并且頁面渲染完畢了
- 如果頁面未更新,則說明微任務在useState更新之前
實驗結果
結果分析
微任務已經執行了,但是頁面還未更新,說明useState并不一定是在微任務之前執行。具體的執行結果與代碼定義順序有關。
類組件中的setState
setState在promise之前定義
export default class Test extends React.Component {
state = {
msg: '我是初始值'
}
handleClick = ()=>{
setTimeout(() => {
console.log('宏任務')
}, 0);
this.setState({
msg: '我是更新值'
},()=>{
console.log('更新了msg:', this.state.msg)
})
Promise.resolve().then(() => {
console.log('微任務觸發msg:', this.state.msg)
})
}
render() {
return (
<div>
<h2>{this.state.msg}</h2>
<button onClick={this.handleClick}>按鈕</button>
</div>
)
}
}
執行結果:
結果說明:當先調用setState,后定義promise時,setState會在微任務之前更新狀態。
setState在promise之后定義
export default class Test extends React.Component {
state = {
msg: '我是初始值'
}
handleClick = ()=>{
setTimeout(() => {
console.log('宏任務')
}, 0);
Promise.resolve().then(() => {
console.log('微任務觸發msg:', this.state.msg)
})
this.setState({
msg: '我是更新值'
}, () => {
console.log('更新了msg:', this.state.msg)
})
}
render() {
return (
<div>
<h2>{this.state.msg}</h2>
<button onClick={this.handleClick}>按鈕</button>
</div>
)
}
}
實驗結果:
結果說明:當先定義promise,后調用setState時,setState會在微任務之后更新狀態。
結論
useState/setState的異步并不是一種在同步之后,微任務之前的特殊情況,而是一種和微任務相同的機制,看見簡單理解為微任務,因為它的更新時機與微任務的調用相同,但react是不是用微任務來實現的更新,我不能確定。
原文鏈接:https://juejin.cn/post/7160661794912993310
相關推薦
- 2022-10-09 淺談重繪和回流的解析_基礎教程
- 2023-06-19 C++開放封閉原則示例解析_C 語言
- 2021-12-01 docker網絡配置過程詳解介紹_Android
- 2022-11-23 Python字符串格式化實例講解_python
- 2022-05-10 原生ajax 在服務器響應前撤銷請求
- 2022-12-30 React錯誤邊界Error?Boundaries詳解_React
- 2022-09-09 Qt?QFtp客戶端實現上傳下載文件_C 語言
- 2022-12-09 ReactQuery系列React?Query?實踐示例詳解_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支