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


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

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

1.問題描述

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

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

 

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.思考問題原因

  下班后思考問題原因。首先,根據props初始化組件state是符合操作邏輯的,不可能不支持;其次,組件中有時能取到,有時取不到。所以一定是我使用有問題,而且較大可以是在錯誤的時間使用了組件。

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

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

仔細看這個結果,也就不難得出結論了。

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

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

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

4.解決方法二

由3可以知道,組件在異步數據到來前已經完成初始化,是導致constructor中無法取到所需數據的原因。所以最直接的方法,就是修改組件創建的時間

//把原來的組件內部控制顯示
/* <ComponentName show={modelName.show}/> */
//更改為狀態直接控制組件是否存在
{
  modelName.show && <ComponentName/> 
}
//或者
{
  modelName.show ? <ComponentName/> : null
}

//或者更嚴謹一點
//由於項目中加入了用戶數據獲取失敗,需重新登錄,所以也就沒有加上后面這個
{
  modelName.show && modelName.needData && <ComponentName/> 
}

修改后

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

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

到此問題算是真正解決。

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

 

 


免責聲明!

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



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