1. 程式人生 > >關於setState 異步 的一些問題

關於setState 異步 的一些問題

同步 回調 turn 一個 ons 就會 struct 批評 touch

關於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 異步 的一些問題