当前位置 : 主页 > 网络编程 > JavaScript >

React18 useState何时执行更新及微任务理解

来源:互联网 收集:自由互联 发布时间:2023-02-01
目录 函数式组件中的useState 测试1 测试2 类组件中的setState setState在promise之前定义 setState在promise之后定义 结论 函数式组件中的useState 前言:众所周知useState是异步的,但网络上对于useS
目录
  • 函数式组件中的useState
    • 测试1
    • 测试2
  • 类组件中的setState
    • setState在promise之前定义
    • setState在promise之后定义
  • 结论

    函数式组件中的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是不是用微任务来实现的更新,我不能确定。

    以上就是React18 useState何时执行更新及微任务理解的详细内容,更多关于React18 useState执行更新的资料请关注自由互联其它相关文章!

    上一篇:React前端解链表数据结构示例详解
    下一篇:没有了
    网友评论