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

常规状况

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

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 (
            <div>
                <h1>{this.state.count}</h1>
                <input type="button" value="点击我" onClick={this.onClick.bind(this)} /><br />
                <br />
            </div>
        )
    }
}

上述执行过程以下:ajax

  1. willmount中的setState会合并成一次执行,count只会保留最后一次的设置,前面的放弃,因此willmount以后是1,并非3;而且在render以前执行,不会引发新的render
  2. render以后执行didMount,setState作一样的处理,这是count2,而且引发新的render
  3. 点击按钮,setState作一样处理,count3,引发新的render

定时器中的setState

定时器中的setState,每次都会引发新的render,即便是同一个定时器中的屡次setStatejson

代码更改为以下:api

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 <div>
            <input type="button" ref={input => this.button = input} onClick={this.onClick.bind(this, 'React事件')} value="生成计时器" />
            <div>Count:{this.state.count}</div>
        </div>
    }
点击按钮,先执行原生事件,再执行react事件,可是原生事件会触发两次render,react事件触发一次。

总结

上述是我对setState的理解,抛砖引玉,但愿帮助你们有方向的去了解react原理机制。刚开始接触,不少同窗想深刻了解,但可能不知道从何入手,这也是我遇到过的困扰,因此如今分享出来,但愿能帮助你们少走弯路,更快的、更有准针对性的去研究学习React。promise


如下为补充内容函数

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

其实在回调函数中,setState是不会触发批量更新机制的,不管是promise,ajax,setTimeout回调等等,同时设置屡次setState,每一个setState都会单独执行并render,由于上下文发生了变化。学习

下面是验证codefetch

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则是truethis

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

相关文章
相关标签/搜索