this.setState的注意事项

发布时间:2024年01月12日

目录

?1、this.setState的注意事项

2、是什么造成了this.setState()的不同步?

3、?那this.setState()什么时候同步,什么时候不同步?

3.1??经过React包装的onClick点击事件()

3.2??没经过React包装的? 原生点击事件


?1、this.setState的注意事项

this.setState(param1, param2);
????????param1: 对象或函数 --- 改变state的值
????????param2: 回调函数 --- 等待state更新后,执行的函数

项目中遇到类似这样的:

【问题】

? ? ? ? 发现 if 语句里拿不到type的值

【原因】

????????this.setState()不保证是同步的,所以在if条件中调用setState修改后的值,是做不到更新

的。

【解决】

? ? ? ? 利用this.setState()的第二个参数:回调函数,在等第一个参数内的state更新后再调用

?【问题】

export default class A extends React.pureComponent {
    constructor(props){
        this.state={
            type: '',
        }
    }


    // 第一个参数:对象
onClick = () => {
    this.setState({
        type: 'asc'
    });
    if(this.state.type=== 'asc'){
        console.log(this.state.type, '0') // ''
        axios.post().then(res => {
            console.log(res, 'res')
        })
    }
};

?【解决】

// 第二个参数:回调函数,在等待第一个参数更新之后调用
onClick = () => {
    this.setState({ 
        type: 'asc', // 第一个参数: 改变state
    }, () => {
        if(this.state.type=== 'asc'){  // 第二个参数:回调函数,用改变后的state值do something
        console.log(this.state.type, '0') // 'asc'
        axios.post().then(res => {
            console.log(res, 'res')
        })
    }
        });
};

2、是什么造成了this.setState()的不同步?

React 的批处理更新导致的(batch the updates)

setState 其实本身执行的过程和代码都是同步的

React为了优化性能,setState()执行时会判断变量isBatchingUpdates的值是true or false, 然后决定是同步更新还是批量更新(从isBatchingUpdates这个变量名就可以直观的看出)

????????????????

3、?那this.setState()什么时候同步,什么时候不同步?

由于isBatchingUpdates默认值是false,即默认是不批量更新的,是立即执行的,是同步的,一行执行完紧接着执行下一行。

但如果this.setState在React合成事件/钩子函数中,React会通过batchedUpdates()这个函数将isBatchingUpdates变成true,即批量更新的,不同步的。


????????

所以主要看调用this.setState()的函数有没有被React包装过图中左侧是没有包装,右侧是经过React包装的如果没经过React包装(not managed by ReactJS), isBatchingUpdates就不会从false变为true,就是同步更新的,代码一行一行的执行

例子:

????????分别用两种方法绑定button的click事件,点击button的时候,改变state的值

3.1??经过React包装的onClick点击事件()

? ? ? ?把这两次打印 console.log('prev state:', this.state.type)、console.log('current state:', this.state.type);? 放到队列中,一起更新,所以第二次打印值与第一次打印值一样
? };

export default class A extends React.pureComponent {


constructor(props) {
    super(props);
    this.state = {
      type: 'origin', // 原始值为 origin
    };
  }
  

changeState = e => {
    console.log('prev state:', this.state.type);
    
    this.setState({
      type: 'changed', // 改变后为 changed
    });
    
    console.log('current state:', this.state.type);
  };



render() {
	console.log('render3');
    return (
      <Button onClick={this.changeState}>改变state</Button>
    );
  }

}

????????打印结果:

????????

? ? ? ?isBatchingUpdates是true,批量更新的,是不同步的,把要执行的内容放到队列中,一起更新,所以第二次打印值与第一次打印值一样

3.2??经过React包装的? 原生点击事件

?????????把这两次打印 console.log('prev state:', this.state.type)、console.log('current state:', this.state.type); 分别打印?,所以第二次打印值与第一次打印值不一样
? };

export default class A extends React.pureComponent {

constructor(props) {
    super(props);
    this.state = {
      type: 'origin', // 原始值为 origin
    };
  }

componentDidMount = e => {
    const dom = document.getElementById('btn');
    dom.addEventListener('click', this.changeState);
}
  

changeState = e => {
    console.log('prev state:', this.state.type);
    
    this.setState({
      type: 'changed', // 改变后为 changed
    });
    
    console.log('current state:', this.state.type);
  };


render() {
	console.log('render');
    return (
      <Button id="btn">改变state</Button>
    );
  }

}

? ? ? ? 打印结果:

????????

isBatchingUpdates是false,说明是同步更新的,一行执行完紧接着执行下一行。
(在输出prev state 这一行之后,遇到第二行的this.setState()就立即执行了,state更新之后就触发了render,然后才输出current state)

这个博主:

http://t.csdnimg.cn/gEM7x

文章来源:https://blog.csdn.net/qq_47305413/article/details/135535619
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。