有问题请教老师

来源:3-14 【异步处理】setState的异步开发

粉墨登场

2021-10-24

alex老师你好,关于 setState() 如果第一个参数是回到函数的话那么数据的更新就变成了同步的了是吗?比如下面这个代码

this.setState((preState) => {
              console.log(preState.count, 'first');
              return { count: preState.count + 1 };
            }, () => {
              console.log(this.state.count, 'third');
            });

            this.setState((preState) => {
              console.log(preState.count, 'second');
              return { count: preState.count + 1 };
            }, () => {
              // console.log(this.state.count);
            });

第一次 set 时打印的是0 first 第二次set打印的是 1 second 第三个打印的是第一个 set 中第二个回调函数参数中的 console 第二次打印的是 第二个 set 中第一个回调参数中的 console 也就是第一次的 set 数据已经被更新加一了。

写回答

1回答

阿莱克斯刘

2021-10-27

你说的基本上正确,实际上setState只是看起来像异步方法而已,准确来说它是一个假异步。之所以会有一种异步方法的表现形式,归根结底还是因为react框架本身的性能机制所导致的,因为每次调用setState都会触发ui渲染,异步处理可以提高性能,将多个状态合并一起更新,减少render方法的调用次数。

当我们的组件执行下面的代码

ddd = ()=> {
    for ( let i = 0; i < 1万; i++ ) {    
        this.setState( { num: this.state.num + 1 } );
    }
}

如果同步执行setState,那么UI的渲染次数也会是1万次。这样的话,系统开销将会是非常巨大的,而用户不会在意过程,他们所关注的也只是最终结果的显示而已。

于是,react的作者就想了个办法,通过强行异步执行setState的方法,把for循环中1万次setState的计算合并在一起,最终在方法ddd结束的时候有且只调用一次render方法渲染UI,从而极大的提高了react程序的运行效率。

不过,我们也可以手动把setState转换为同步方法,当我们使用这种setState语法结构的时候

ddd = ()=> {
    for ( let i = 0; i < 1万; i++ ) {  
        this.setState((preState) => {
            return { { num: this.state.num + 1 }};
        }, () => {
            // console.log(this.state.num)
        });
    }
}

就相当于ddd方法没执行完成的时候,在每次for循环中都强制渲染UI,所以看起来setState就变成同步执行了。

2
2
粉墨登场
非常感谢!
2021-10-27
共2条回复

React18 系统精讲 结合TS打造旅游电商平台

React18 精讲 + 结合 TS 实战 + 热门业务开发,获取必备技能

1993 学习 · 1015 问题

查看课程