关于setState 异步 的一些问题

Posted 木子飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于setState 异步 的一些问题相关的知识,希望对你有一定的参考价值。

关于setState ,我们首先要有个正确的认识,官网中给出的解释是setState不是保证同步的

这说明它有时候是同步的有时候的异步的,那什么时候是同步,什么时候是异步?

答案是在React库控制之内时,它就会以异步的方式来执行,否则以同步的方式执行。

但大部份的使用情况下,我们都是使用了React库中的组件,例如View、Text、Image等等,

它们都是React库中人造的组件与事件,是处于React库的控制之下,在这个情况下,

setState就会以异步的方式执行。

比如这里有个例子

constructor(props) {
    super(props);
    this.state = {
      name:"lisi"
    };
  }

pushnext(){
    this.setState({
      name:"zhangsan"
    });
  
alert(this.state.name)
}
ListHeaderComponent() {
  return (
   
<TouchableOpacity onPress={()=>this.pushnext()}>
   <Text style={{width: deviceWidth,backgroundColor: ‘yellow‘ }}>这是头部</Text>
    </TouchableOpacity>
  )
}

我这里pushnext()方法里面alet 的东西就是"lisi",因为这里setState 在这里是异步执行,那么

要想alert出来"zhangsan"应该怎么做呢?

有两种方式

 一、使用setState的第二传参,传入一个回调(callback)函式,改为像下面这样的代码

pushnext(){
    this.setState({
      name:"zhangsan"
    } ,function(){
        alert(this.state.name)
     });
}

 二、使用InteractionManager.runAfterInteractions

pushnext(){
    this.setState({
      name:"zhangsan"
    });
InteractionManager.runAfterInteractions(() => {
           alert(this.state.name);
        });
}

 

关于setState异步执行还有一个衍生的问题值得探讨就是它独特存在的

setState可能会引发不必要的渲染(renders)

state本身的设计是无法直接更改,setState的设计是用来更动state值,

也会触发重新渲染(re-render),按照逻辑就是反正不管如何,只要开发者呼叫setState

React就去作整个视图的重新渲染就是。所以setState必定会作重新渲染的执行,只是要如何渲染是由React来决定。

重新渲染(re-render)指的主要是页面上视图(View)的重新再呈现,这是React原本的核心设计,

但这个设计是有一些问题的。最主要的是state(状态)并不一定单纯只用来记录与视图(View)有关的状态,

也有可能是某个内部控制用的属性值,或是只套用在内部使用的资料。当你改变了这些与视图无关的state(状态)值,

以现在的React设计来说,照样要触发重新渲染的执行过程,这在某些复杂的应用时,由于造成不必要的渲染,

也有可能造成效能上的问题。

 

React提供了shouldComponentUpdate方法让开发者可以自行判断,自行提供对应的解决方式,

算得上是一种补墙的方法

那么shouldComponentUpdate怎么使用呢?

我们假如一个场景,在一个界面,你在push到下一个界面的时候有个setState方法,如:

pushnext(){
    this.setState({
      name:"zhangsan"
    } ,function(){ 
      this.props.navigation.navigate(‘Chat‘,{name:this.state.name});
     });
}

你要把这个name传给下一个界面,但是你传的时候有setState,这就会导致该界面又会render一遍,

(有兴趣的小伙伴可以测试一下)这个时候,我们就可以用到shouldComponentUpdate。

我的代码如下

shouldComponentUpdate(nextProps, nextState){
     return this.state.others !== nextState.others;
  }

这句话什么意思呢?这里的 this.state.others 其实是我这个界面需要渲染出来的值,它是我通过网络获取的,

网络获取之前render第一遍,这个时候this.state.others是空,网络获取后this.state.others有值了,

在 shouldComponentUpdate里面一判断发现两者不一样,返回true,然后开始执行render,

把this.state.others render出来了,之后在执行上面的 pushnext()方法,本来要执行render()方法的,

但是一执行shouldComponentUpdate()方法 ,发现这两个值是没有改变,是一样的,所以不再render,

跳转到下一界面。

 

以上就是我对setState的理解,如有不正确的地方,欢迎大家指正批评


 

以上是关于关于setState 异步 的一些问题的主要内容,如果未能解决你的问题,请参考以下文章

React 的 setState 是异步的还是啥?

从零开始实现一个React:异步的setState

setState何时同步,何时异步,为什么?

关于其活动的片段生命周期

多次调用函数时 setState 不会发生变化

reactjs——解决setState异步问题