react之setState異步和同步問題


1). setState()更新狀態是異步還是同步的?
        a. 執行setState()的位置?
            在react控制的回調函數中: 生命周期勾子 / react事件監聽回調
            非react控制的異步回調函數中: 定時器回調 / 原生DOM事件監聽回調 / promise回調 /...
        b. 異步 OR 同步?
            react相關回調中(生命周期回調、事件監聽回調): 異步
            其它異步回調中(定時器、原生DOM事件監聽回調、Promsie回調): 同步
驗證如下:
import React, { Component } from 'react'

class Demo extends Component {
    state = {
        count:0
    }
    /**異步更新:react事件監聽回調里,setState是異步更新的 */
    update1 = () => {
        console.log('update1 更新前',this.state.count)
        this.setState(state=>({count:state.count+1}))
        console.log('update1 更新后',this.state.count)
    }
    /**異步更新:react生命周期回調函數里,setState是異步更新的 */
    componentDidMount(){
        console.log('componentDidMount 更新前',this.state.count)
        this.setState(state=>({count:state.count+1}))
        console.log('componentDidMount 更新后',this.state.count)
    }
    /**同步更新:定時器回調  */
    update2 = () => {
        setTimeout(()=>{
            console.log('定時器 更新前',this.state.count)
            this.setState(state=>({count:state.count+1}))
            /**setState導致狀態更新流程觸發,更新完畢后才執行下面代碼,所以這里為同步更新 */
            console.log('定時器 更新后',this.state.count)
        },3000)
    }
    /**同步更新:原生DOM事件監聽回調---結合ref  */
    update3 = () => {
        let count_dom = this.refs.count_dom
        count_dom.onclick = () => {
            console.log('原生DOM事件監聽回調 更新前',this.state.count)
            this.setState(state=>({count:state.count+1}))
            console.log('原生DOM事件監聽回調 更新后',this.state.count)
        }
    }
    /**同步更新:promise回調  */
    update4 = () => {
        Promise.resolve().then(value=>{
            console.log('promise 更新前',this.state.count)
            this.setState(state=>({count:state.count+1}))
            console.log('promise 更新后',this.state.count)
        })
    }
    render() {
        const {count} = this.state
        console.log('render渲染',count)
        return ( 
            <>
                <h2 ref="count_dom">{count}</h2>
                <button onClick={this.update1}>更新1</button>
                <button onClick={this.update2}>更新2</button>
                <button onClick={this.update3}>更新3</button>
                <button onClick={this.update4}>更新4</button>
                <button onClick={this.update5}>更新5</button>
            </>
        );
    }
}
 
export default Demo;

由上述可得知如下案例里,可以同步獲取setState改動后的數據

原因:該setState操作在await即promise回調里,所以是同步的

  

 

 

    
 2). 關於異步的setState()
        a. 多次調用, 如何處理?
            setState({}): 合並更新一次狀態, 只調用一次render()更新界面 ---狀態更新和界面更新都合並了
            setState(fn): 更新多次狀態, 但只調用一次render()更新界面  ---狀態更新沒有合並, 但界面更新合並了
        b. 如何得到異步更新后的狀態數據?
            在setState()的callback回調函數中
    測試代碼如下:
import React, { Component } from 'react'

class Demo extends Component {
    state = {
        count:0
    }
    /**異步的setState({})多次調用:合並更新一次狀態(即覆蓋之前更新), 只調用一次render()更新界面,狀態更新和界面更新都合並了 */
    update5 = () => {
        console.log('update5-1 更新前',this.state.count)
        this.setState({count:this.state.count+1})
        console.log('update5-1 更新后',this.state.count)
        console.log('update5-2 更新前',this.state.count)
        this.setState({count:this.state.count+1})
        console.log('update5-2 更新后',this.state.count)
    }
    /**異步的setState(fn)多次調用:更新多次狀態(不會合並,即不會覆蓋之前更新), 但只調用一次render()更新界面,狀態更新沒有合並, 但界面更新合並了 */
    update6 = () => {
        console.log('update6-1 更新前',this.state.count)
        this.setState(state=>({count:state.count+1}))
        console.log('update6-1 更新后',this.state.count)
        console.log('update6-2 更新前',this.state.count)
        this.setState(state=>({count:state.count+1}))
        console.log('update6-2 更新后',this.state.count)
    }
    /**異步的setState(fn)+setState({})組合調用*/
    update7 = () => {
        console.log('update7-1 更新前',this.state.count)
        this.setState({count:this.state.count+1})
        console.log('update7-1 更新后',this.state.count)
        console.log('update7-2 更新前',this.state.count)
        this.setState(state=>({count:state.count+1}))
        console.log('update7-2 更新后',this.state.count)
    }
    render() {
        const {count} = this.state
        console.log('render渲染',count)
        return ( 
            <>
                <h2>{count}</h2>
                <button onClick={this.update5}>更新5</button>
                <button onClick={this.update6}>更新6</button>
                <button onClick={this.update7}>更新7</button>
            </>
        );
    }
}
 
export default Demo;

  

 

 

 

 

.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM