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