React学习笔记15-13-setState同步异步问题

发布时间 2023-10-31 14:18:25作者: SadicZhou

先说结论:

setState处在同步的逻辑中会异步更新状态,更新真实dom。
连续调用 setState 不会连续进行虚拟dom的对比和页面的更新
setState处在异步的逻辑中,同步更新状态,更新真实dom。
 

1.同步状态

先看同步状态

/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react'

export default class App extends Component {
    state = {
        count: 1
    }
    render() {
        return (
            <div>  
                <div>{this.state.count}</div>
                <button onClick={
                    () => {
                      
                  
            
this.setState({
count: this.state.count + 1
})
console.log(this.state.count)
this.setState({
count: this.state.count + 1
})
console.log(this.state.count)
this.setState({
count: this.state.count + 1
})


                    }
                
                }>add1</button>
          
            </div>
        )
    }
}

 可以看出来三个打印都是1,说明setState在同步环境下是异步进行更新的

 并且执行了三次setState实际上只更新了一次dom

这是因为

react会根据是同步队列还是异步队列来指定一个来决定setState是否合并处理的标志位,

同步队列为true,
这时setState会异步执行,进行合并处理,
因为跟新的都是同一个状态所以会
合并为 this.setState({
count: this.state.count + 1
})
连续调用只会更新一次dom

2.同步状态下,如何获取dom更新后的state

/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react'

export default class App extends Component {
    state = {
        count: 1
    }
    render() {
        return (
            <div>
                <div>{this.state.count}</div>
                <button onClick={
                    () => {
                       
                        //  this.setState的第二个参数是一个函数,
                        //可以看做状态更新和dom后的回调
                        this.setState({
                            count: this.state.count + 1
                        }, () => {
                            console.log(this.state.count)
                        })

                        this.setState({
                            count: this.state.count + 1
                        }, () => {
                            console.log(this.state.count)
                        })
                        this.setState({
                            count: this.state.count + 3
                        }, () => {
                            console.log(this.state.count)
                        })
                        /*  同步逻辑下,在setState的回调中可以打印出更新后的状态。这里因为是
                            合并处理,所以以最后一个为准,打印出来是1+3 = 4
                        */


                    }
             
                }>add1</button>
             
            </div>
        )
    }
}

 如果在同步情况下想要获取dom更新后的state可以通过setState的第二个参数来获取

  this.setState的第二个参数是一个函数,可以看做状态更新和dom后的回调

 同步逻辑下,在setState的回调中可以打印出更新后的状态。这里因为是
    合并处理,所以以最后一个为准,打印出来是1+3 = 4
3.异步状态
/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react'

export default class App extends Component {
    state = {
        count: 1
    }
    render() {
        return (
            <div>
                <div>{this.state.count}</div>
                <button onClick={
                    () => {
                        setTimeout(() => {
                            //异步逻辑
                            this.setState({
                                count: this.state.count + 1
                            })
                            console.log(this.state.count)
                            this.setState({
                                count: this.state.count + 1
                            })
                            console.log(this.state.count)
                            this.setState({
                                count: this.state.count + 1
                            })
                            console.log(this.state.count)
                        }, 0);
                    }
                }>add</button>
            </div>
        )
    }
}

 可以看到在异步状态下setState是同步调用的每次更新状态都会被打印下来,并且同步会更新状态和dom