react+dva 全局model中異步獲取數據state在組件中取不到值

先上結論,不是取不到,是寫法有問題。react

全文分4部分,1是問題描述,2是一開始的解決想法(錯誤作法),3是問題產生緣由的思考,4是正常解決方法。只想看結論直接跳4框架

1.問題描述異步

  接觸react dva一個月,和同事都不算熟悉框架。在修改、使用同事的ui組件時,想用全局model保存的state來給組件state一個初始值,但組件中取不到登陸後異步獲取的用戶信息。ide

  在組件constructor中取不到(僅有model state初始化的值,無異步獲取的信息),但在組件使用時render中能夠console出須要的值ui

 

2.解決方法一(錯誤方法)
  因爲render中能夠獲取到須要的值,因此第一反應是在這拿到須要的值,而後改變組件state給予組件初始值。
  但直接在render中使用setState很明顯是會出錯的,修改狀態觸發從新渲染,渲染中修改狀態,又重渲染的死循環setState -> render -> setState -> render... ...
  因此加上了個條件若是state中沒有值,才修改state
if(!this.state.needData) { this.setState({ needData: this.props.modelName.needData }) }
View Code

 

保存看效果,貌似一切正常,組件按照須要的狀況正常工做。感受上好像是可行的解決方法,但其實並非,這是錯誤而拙劣的手法。很明顯這種方法是不受推薦的

3.思考問題緣由this

  下班後思考問題緣由。首先,根據props初始化組件state是符合操做邏輯的,不可能不支持;其次,組件中有時能取到,有時取不到。因此必定是我使用有問題,並且較大能夠是在錯誤的時間使用了組件。spa

那就須要定位問題所在,這時候console是個簡單原始,但確實有效的幫手。code

把頁面入口組件(0)問題組件constructor(1)問題組件render(2)model setup(3)異步數據獲取到(4)分別加上consoleblog

仔細看這個結果,也就不可貴出結論了。生命週期

組件constructor初始化組件在異步數據加載以前就已經完成,且數據加載之後,全局state修改觸發的從新渲染並不會影響到constructor,其在組件生命週期裏僅會執行一次。

而查看該組件調用處發現,該組件是否顯示(彈出組件,非一直顯示)是把控制的flag傳入了組件裏,在組件內部控制是否顯示。這種方式其實僅能控制組件內的元素是否顯示,沒法控制組件自己是否存在。正是這個緣由,致使了組件在頁面加載的以後便已經初始化完畢,以後僅控制顯示與否。這其實不利於頁面加載速度,也不符合按需加載的思想,還會致使異步數據初始化組件失敗。因此我以爲不是個好的寫法。

那麼也就有了第二種,我認爲正確的解決方案

4.解決方法二

由3能夠知道,組件在異步數據到來前已經完成初始化,是致使constructor中沒法取到所需數據的緣由。因此最直接的方法,就是修改組件建立的時間

//把原來的組件內部控制顯示 /* <ComponentName show={modelName.show}/> */
//更改成狀態直接控制組件是否存在
{ modelName.show && <ComponentName/> 
} //或者
{ modelName.show ? <ComponentName/> : null
} //或者更嚴謹一點 //因爲項目中加入了用戶數據獲取失敗,需從新登陸,因此也就沒有加上後面這個
{ modelName.show && modelName.needData && <ComponentName/> 
}

修改後

目標組件不會在頁面加載時就初始化

而是在用戶點擊控制按鈕,須要使用組件時,才初始化

到此問題算是真正解決。

由此問題,也讓我對model加載、頁面初始化、有狀態組件初始化、組件生命週期,有了更深的理解,算是有些收穫。

相關文章
相關標籤/搜索