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

學無先后,達者為師

網站首頁 編程語言 正文

React18?useState何時執行更新及微任務理解_React

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

函數式組件中的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

欄目分類
最近更新