日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

React18?useState何時執(zhí)行更新及微任務(wù)理解_React

作者:郎心似鐵 ? 更新時間: 2022-12-04 編程語言

函數(shù)式組件中的useState

前言:眾所周知useState是異步的,但網(wǎng)絡(luò)上對于useState何時異步更新并沒有一個共識,為了探究,做一個簡單的實(shí)驗(yàn),實(shí)驗(yàn)?zāi)康氖翘骄縰seState與微任務(wù)、宏任務(wù)的先后關(guān)系

測試1

實(shí)驗(yàn)步驟:點(diǎn)擊按鈕觸發(fā)事件,在事件中我們做三件事:修改state/定義一個宏任務(wù)setTimeout /定義一個微任務(wù)promise.then?,我們在微任務(wù)中打上debugger,暫停代碼,觀察此時頁面是否更新了數(shù)據(jù)。

實(shí)驗(yàn)代碼

import React, { useState } from 'react'
export default function Test() {
    const [msg, setMsg] = useState('我是初始值')
    const onChange = () => {
        setMsg('我是更新值')
        setTimeout(() => {
            console.log('宏任務(wù)')
        }, 0);
        Promise.resolve().then(res=>{            
            debugger  
            console.log('微任務(wù)')         
        })
    }
    return (
        <div>
            <h2>{msg}</h2>
            <button onClick={onChange}>按鈕</button>
        </div>
    )
}

實(shí)驗(yàn)期望:

  • 如果頁面更新了,則說明在微任務(wù)之前,useState就已經(jīng)更新了狀態(tài),并且頁面渲染完畢了
  • 如果頁面未更新,則說明微任務(wù)在useState更新之前

實(shí)驗(yàn)結(jié)果

結(jié)果分析 結(jié)果符合第一種期望,useState在此微任務(wù)之前就完成了,由此得出useState異步更新是在微任務(wù)之前,同步代碼之后的結(jié)果,這是不準(zhǔn)確的。讓我們進(jìn)一步測試。

測試2

實(shí)驗(yàn)步驟:測試2在廁所1上調(diào)整下順序。定義宏任務(wù)/定義微任務(wù)/修改state

實(shí)驗(yàn)代碼:

import React, { useState } from 'react'
export default function Test() {
    const [msg, setMsg] = useState('我是初始值')
    const onChange = () => {
        setTimeout(() => {
            console.log('宏任務(wù)')
        }, 0);
        Promise.resolve().then(res=>{            
            debugger  
            console.log('微任務(wù)')         
        })
        setMsg('我是更新值')
    }
    return (
        <div>
            <h2>{msg}</h2>
            <button onClick={onChange}>按鈕</button>
        </div>
    )
}

實(shí)驗(yàn)期望

  • 如果頁面更新了,則說明在微任務(wù)之前,useState就已經(jīng)更新了狀態(tài),并且頁面渲染完畢了
  • 如果頁面未更新,則說明微任務(wù)在useState更新之前

實(shí)驗(yàn)結(jié)果

結(jié)果分析

微任務(wù)已經(jīng)執(zhí)行了,但是頁面還未更新,說明useState并不一定是在微任務(wù)之前執(zhí)行。具體的執(zhí)行結(jié)果與代碼定義順序有關(guān)。

類組件中的setState

setState在promise之前定義

export default class Test extends React.Component {
    state = {
        msg: '我是初始值'
    }
    handleClick = ()=>{
        setTimeout(() => {
           console.log('宏任務(wù)') 
        }, 0);
        this.setState({
            msg: '我是更新值'
        },()=>{
            console.log('更新了msg:', this.state.msg)
        })
        Promise.resolve().then(() => {
            console.log('微任務(wù)觸發(fā)msg:', this.state.msg)
        })
    }
  render() {
    return (
      <div>
            <h2>{this.state.msg}</h2>
        <button onClick={this.handleClick}>按鈕</button>
      </div>
    )
  }
}

執(zhí)行結(jié)果:

結(jié)果說明:當(dāng)先調(diào)用setState,后定義promise時,setState會在微任務(wù)之前更新狀態(tài)。

setState在promise之后定義

export default class Test extends React.Component {
    state = {
        msg: '我是初始值'
    }
    handleClick = ()=>{
        setTimeout(() => {
           console.log('宏任務(wù)') 
        }, 0);
        Promise.resolve().then(() => {
            console.log('微任務(wù)觸發(fā)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>
    )
  }
}

實(shí)驗(yàn)結(jié)果:

結(jié)果說明:當(dāng)先定義promise,后調(diào)用setState時,setState會在微任務(wù)之后更新狀態(tài)。

結(jié)論

useState/setState的異步并不是一種在同步之后,微任務(wù)之前的特殊情況,而是一種和微任務(wù)相同的機(jī)制,看見簡單理解為微任務(wù),因?yàn)樗母聲r機(jī)與微任務(wù)的調(diào)用相同,但react是不是用微任務(wù)來實(shí)現(xiàn)的更新,我不能確定。

原文鏈接:https://juejin.cn/post/7160661794912993310

欄目分類
最近更新