react 關於this.setState使用時,第一次無法獲取數據,第二次獲取的數據是第一次觸發的疑問


我使用的是antd組件,

compareClickFn(orderCodes, fileNames) {
    printLog("orderCodes----------"+ orderCodes); printLog("fileNames----------"+ fileNames); this.setState({ show: !this.state.show, orderCode: orderCodes, fileName: fileNames, }); printLog("orderCode and fileName------"+ this.state.show + "----" + this.state.fileName); const ShowAnim = document.getElementById('ShowAnim'); if (this.state.show === false) { ShowAnim.style.display = 'block'; this.state.type = 'primary'; } else { ShowAnim.style.display = 'none'; this.state.type = 'ghost'; } }

這段代碼是<Button>組件的onclick事件函數,其中orderCoder和fileName已經獲取到了,我想要將這些值保存進入this.state中對應的變量里,但是在觸發事件時,出現了第一次點擊的時候並沒有將數據傳遞進去,在第二次點擊的時候將第一次的數據傳遞進去了,這個問題該如何解決?

 

4個回答

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; /* MobX managed instance state */ constructor(props, context) { super(props, context) this.selection = props.values[0] } //...

上面代碼取自這篇文章的里: 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

和 antd 沒關系。

setState 是異步的:https://facebook.github.io/re...

0

在setState回調里寫要做的事情

 

引用原文:https://segmentfault.com/q/1010000007343714

 

寫博客是為了記住自己容易忘記的東西,另外也是對自己工作的總結,文章可以轉載,無需版權。希望盡自己的努力,做到更好,大家一起努力進步!

如果有什么問題,歡迎大家一起探討,代碼如有問題,歡迎各位大神指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM