资讯专栏INFORMATION COLUMN

React中setState几个现象---先知道再理解

tomlingtm / 3493人阅读

摘要:原生事件中的在按钮原生事件中定义的和定时器效果一样,每次都会引起新的事件是合并的成一次的。原生事件事件生成计时器点击按钮,先执行原生事件,再执行事件,但是原生事件会触发两次,事件触发一次。

常规情况

在同一个方法中多次setState是会被合并的,并且对相同属性的设置只保留最后一次的设置;

import React from "react";

export class Test extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0
            
        };
    }
    componentWillMount() {
        let me = this;
        me.setState({
            count: me.state.count + 2
        });
        me.setState({
            count: me.state.count + 1
        });
    }
    componentDidMount() {
        let me = this;
        me.setState({
            count: me.state.count + 2
        });
        me.setState({
            count: me.state.count + 1
        });
    }

    onClick() {
        let me = this;
        me.setState({
            count: me.state.count + 1
        });
        me.setState({
            count: me.state.count + 1
        });
    }

    render() {
        console.log(this.state.count);
        console.log("1111111111111111111111111111111111111111111");
        return (
            

{this.state.count}



) } }

上述执行过程如下:

willmount中的setState会合并成一次执行,count只会保留最后一次的设置,前面的放弃,所以willmount之后是1,并不是3;并且在render之前执行,不会引起新的render

render之后执行didMount,setState做同样的处理,这是count2,并且引起新的render

点击按钮,setState做同样处理,count3,引起新的render

定时器中的setState

定时器中的setState,每次都会引起新的render,即使是同一个定时器中的多次setState

代码更改成如下:

    componentWillMount() {
        let me = this;
        setTimeout(() => {
            me.setState({
                count: me.state.count + 1
            });
            me.setState({
                count: me.state.count + 1
            });
        }, 0);
    }
    
       componentDidMount() {
        let me = this;
        setTimeout(() => {
            me.setState({
                count: me.state.count + 1
            });
            me.setState({
                count: me.state.count + 1
            });
        }, 0);
    }
    
    onClickTime() {
        let me = this;
        setTimeout(() => {
            me.setState({
                count: me.state.count + 1
            });
            me.setState({
                count: me.state.count + 1
            });
        }, 0);
    }
上述代码,每次setState都会引发新的render,需要深入了解的可以查查setState的原理,简单理解是定时器中的setState没走react的事物机制,执行时批量更新没被设置true,所以每次都直接render了。
原生事件中的setState
在按钮原生事件中定义的setState,和定时器效果一样,每次setState都会引起新的render
react事件是合并的成一次render的。
 componentDidMount() {
        this.button.addEventListener("click", this.onClick.bind(this, "原生事件"), false);
 }
    
 onClick(info) {
        console.log(info);
        this.setState({
            count: ++count
        });
        this.setState({
            count: ++count
        });
    }

    render() {
        console.log(this.state.count);
        return 
this.button = input} onClick={this.onClick.bind(this, "React事件")} value="生成计时器" />
Count:{this.state.count}
}
点击按钮,先执行原生事件,再执行react事件,但是原生事件会触发两次render,react事件触发一次。
总结

上述是我对setState的理解,抛砖引玉,希望帮助大家有方向的去了解react原理机制。刚开始接触,很多同学想深入了解,但可能不知道从何入手,这也是我遇到过的困扰,所以现在分享出来,希望能帮助大家少走弯路,更快的、更有准针对性的去研究学习React。

以下为补充内容

回调不会触发react的批量更新机制

其实在回调函数中,setState是不会触发批量更新机制的,无论是promise,ajax,setTimeout回调等等,同时设置多次setState,每个setState都会多带带执行并render,因为上下文发生了变化。

下面是验证code

  onClickBtn = () => {
    // const promise = new Promise((resolve, reject) => {
    //   this.setState({ count: this.state.count + 1 });
    //   console.log(this.state.count);
    //   this.setState({ count: this.state.count + 1 });
    //   console.log(this.state.count);
    //   resolve();
    // });

    // promise.then(() => {
    //   this.setState({ count: this.state.count + 1 });
    //   console.log(this.state.count);
    //   this.setState({ count: this.state.count + 1 });
    //   console.log(this.state.count);
    // });

    fetch("/api/getlist")
      .then(response => {
        return response.json();
      })
      .then(data => {
        console.log(JSON.stringify(data));
        this.setState({ count: this.state.count + 1 });
        console.log(this.state.count);
        this.setState({ count: this.state.count + 1 });
        console.log(this.state.count);
      });
  };
生命周期和事件中多次setState的区别

在写demo时发现,虽然didMount中的多次setState会被合并,符合正常的规律,但是通过调试发现,在didMountisBatchingUpdates始终是false,而事件调用触发的setStateisBatchingUpdates则是true

---------------------转载请标明出处!--------------------

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94451.html

相关文章

  • [ 一起学React系列 -- 2 ] UI的灵魂--State

    摘要:首先卖个关子,下面我们一起来复习下小学还是初中的一枚数学知识。一旦更改了,会触发组件的重新渲染。为了页面渲染性能的考虑,有助于在中进行比较并确定是否重新渲染。 概念引入 对于React来说, 没有State就没有页面的渲染, 我们也将什么都看不到 咋一听怎么那么唬人?不过的确是这样,正如标题所言State是UI的灵魂。我们都知道React的核心思想之一是组件化,将页面所展示的东西按一定...

    XBaron 评论0 收藏0
  • React 深入系列4:组件的生命周期

    摘要:因为是深入系列文章,本文不会仔细介绍每个生命周期方法的使用,而是会重点讲解在使用组件生命周期时,经常遇到的疑问和错误使用方式。父组件发生更新导致的组件更新,生命周期方法的调用情况同上所述。 文:徐超,《React进阶之路》作者授权发布,转载请注明作者及出处 React 深入系列4:组件的生命周期 React 深入系列,深入讲解了React中的重点概念、特性和模式等,旨在帮助大家加深...

    warnerwu 评论0 收藏0
  • 记录一次利用Timeline Performance工具进行 React性能优化的真实案例

    摘要:出现红帧表示页面已经超负荷,会出现卡顿,响应缓慢等现象。因此当滑动周日历时已经不会有红帧发生了。我的目的是每一次递归会调用一次与但是这样写只会在递归结束时调用一次因此修改如下这样优化之后,发现内存占用下降一些,但是红帧仍然存在。 性能优化可以说是衡量一个前端程序员react使用水平的重要标准。 在学习react之初的时候,由于对react不够了解,写的项目虽然功能都实现了,但是性能优化...

    jsyzchen 评论0 收藏0

发表评论

0条评论

tomlingtm

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<