zoukankan      html  css  js  c++  java
  • 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;
    

      

    .

  • 相关阅读:
    Js 之获取QueryString的几种方法
    Go语言 之md5加密
    跨域取文件(跨项目)
    System.IO
    System.Threading.Tasks
    JS存取Cookies值,附自己写的获取cookies的一个方法
    HttpServerUtility 和 HttpUyility
    JS格式化时间
    JS获取页面传过来的值
    Navigator 对象
  • 原文地址:https://www.cnblogs.com/fightjianxian/p/12630036.html
Copyright © 2011-2022 走看看