0
已采納
setState其實並不是異步的,它在整個執行過程中沒有任何的setTimeout或者promise等異步操作。
你可以嘗試下在setTimeout(或者自己綁定的DOM事件,但是不要在JSX中綁定事件哦,要自己手動addEventListener,目的就是擺脫React的控制
)中調用setState(newState)方法,然后緊接着log看下你設置的新的state有沒有起作用呢?如果再仔細一些,你還可以研究下這次的setState、render、log的執行順序是怎樣的呢?
不要被setState的名字欺騙了,它其實是 set pending state
—— 將你傳入的newState放入一個待更新的隊列,到此為止你的setState方法基本已經完成了它所有的工作。
真正執行state合並更新的另有其人 —— transaction
,對於React的transaction網上有相應的講解,在這里不再贅述,有興趣可以看下Transaction源碼以及ReactUpdates源碼
setTimeout中setState和在生命周期里setState的區別在於,setTimeout中的setState會自己觸發一個transaction,而生命周期中的setState已經處於React生命周期的transaction中了。
最后:如果想在newState起效后執行一些處理,最好還是放在setState的回調中哦
2
this.setState是異步的,所以你一呼叫this.setState完,馬上作獲取this.state中的值,不一定能獲取得到改變的值。
1. 用this.setState的第二參數,給一個回調來在更新后執行,例如:
this.setState({ something: true }, () => console.log(this.state))
2. 用componentDidUpdate()
這個生命周期方法,把確定更新后要作的代碼放里面。
3. mobx有神奇的@observer
與@observable
可以作這事。
@observer class Select extends React.Component { @observable selection = null;
上面代碼取自這篇文章的里: https://medium.com/@mweststra...
以下是補充"為何說setState是異步的?"的回答
setState
並非使用setTimeout或promise的那種進入到事件回圈(Event loop)的異步執行,但它的執行行為在React庫中控制時,的確是異步的。以最精確的說法來說,"它不是保證同步的",官方的說明也是如此。
setState
包含在其中執行過程是一個很復雜的過程,從最初的版本到現在,也有無數次的修改。它的工作除了要設定this.state
之外,還要負責觸發重渲染,這里面需要經過React核心中演算法,也就是virtual DOM的演算,最終才能決定是否要進行重渲染,以及如何渲染。為了批次與效能的理由,多個setState呼叫有可能在過程中要進行合並,所以它被設計以異步來執行是合理的,但這主要限於在React庫的控制之中。
那么setState會在何時以同步的方式來執行,也就是立即更動this.state
?答案是在React函式庫控制之外時,它就會以同步的方式來執行,在下面兩篇文章中,都有類似的例子:
但大部份的使用情況下,我們都是使用了React庫中的表單控件,例如select, button,這些是React庫中人造的控件與事件,是處於React庫的控制之下,setState
就會以異步的方式執行。所以一般來說,我們會認為setState
就是異步執行,並不是用源代碼來看說它是不是有使用setTimeout或Promise之類的方式轉為JS的異步執行方式,而是以它在React庫的控制之下,以執行行為與順序來理解。
以下是翻譯自官方setState源碼的注解,其實如果是官網的說明也是類似的說明:
不保證this.state
會立即更新,所以在調用這個方法后存取this.state
可能會回傳舊的值。
不保證調用setState
就會同步地執行,而它們也可能最終被被批量調用(多次調用的情況下)。你可以提供額外的回調,回調將會在setState
實際被完成時被執行。
0
0