阅读 804

高频面试题:setState是同步还是异步

​ 关于React高频面试题:setState是同步还是异步?,笔者相信大部分react技术栈求职者都被问到过,本文主要总结一下笔者对于这个问题的一点理解,希望能给各位同学解决一丝困惑,不足之处请各位大佬多多指正。

​ 笔者习惯通过代码的运行结果来总结结论和规律,世间万物都有其规律,本文也会结合一些demo来总结关于这个问题的答案。这样也是最有说服力的,废话不多说,上酸菜(错了错了...是上代码)

// demo1 
class App extends React.Component {
        state = {
          num: 0
        };
        componentDidMount() {
          	this.setState({
           	num: this.state.num + 1
           });
        	this.setState({
           	num: this.state.num + 2
          });
          console.log(this.state.num);
        }
 	render() {
          const { num } = this.state;
          return <div>{ num }</div>;
        }
      }
      ReactDOM.render(<App />, document.getElementById('root'));
// 控制台打印0,界面显示2
复制代码

通过显示结果,我们可以得出结论一:在生命周期的函数场景下,setState是异步的,相同的状态属性多次更新会合并成一次,且最后一次会生效保留

// demo2
class App extends React.Component {
        state = {
          num: 0
        };
      handleClick = () => {
          this.setState({
            num: this.state.num + 1
          });
          this.setState({
            num: this.state.num + 2
          });
          console.log(this.state.num); // 点击num控制台打印0,界面显示2
      };
 	render() {
         const { num } = this.state;
         return <div onClick={this.handleClick}>{ num }</div>;
        }
      }
      ReactDOM.render(<App />, document.getElementById('root'));
复制代码

我们给div注册了一个click事件,界面渲染完之后,num显示是0,点击num显示2,控制台打印0,由于显示结果一样,笔者就没有配图,大家可以自行测试。通过该结果我们可以得出结论二:在React合成事件的场景下,setState是异步,关于React合成事件的概念,笔者会在文章最后解答,大佬可以去阅读React源码。(在这里onClick事件并不是JS原生事件,而是React合成事件)

// demo3
class App extends React.Component {
        state = {
          num: 0
        };
        componentDidMount() {
       	  setTimeout(() => {
            this.setState({
              num: this.state.num + 1
            });
            this.setState({
              num: this.state.num + 2
            });
            console.log(this.state.num); // 控制台打印3
          }, 1000);
        }
 	render() {
          const { num } = this.state;
          return <div>{ num }</div>;
        }
      }
      ReactDOM.render(<App />, document.getElementById('root'));
复制代码

界面渲染完毕,一秒钟后,页面和控制台都显示3。通过该结果,我们可以得出结论三:在定时器的场景下,setState是同步的,会依次更新。还有一种情况,在原生DOM事件场景下setState也是同步的,我们可以通过ref获取到原生DOM,绑定事件去检测,由于篇幅有限就不多赘述了。最后,解释下React合成事件的概念和做一个全面的总结。

React合成事件的机制:React并不是将click事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数处理运行。

如果DOM上绑定了过多的事件处理函数,整个页面响应以及内存占用可能都会受到影响。React为了避免这类DOM事件滥用,同时屏蔽底层不同浏览器之间的事件系统差异,实现了一个中间层——SyntheticEvent。

当用户在为onClick添加函数时,React并没有将Click事件绑定在DOM上面。而是在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装交给中间层SyntheticEvent(负责所有事件合成)所以当事件触发的时候,会使用统一的分发函数dispatchEvent将指定函数执行。

总结:1,在生命周期函数,React合成事件场景下是异步:相同的状态属性(不同的状态属性不会影响)多次更新会合并成一次,最后一次会保留。 2,在定时器、原生DOM事件场景下是同步:会依次更新

文章分类
前端
文章标签