av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

奇怪的useMemo知識增加了

 作為「性能優(yōu)化」手段,一般用useMemo緩存函數(shù)組件中比較消耗性能的計算結(jié)果:

成都創(chuàng)新互聯(lián)公司,為您提供成都網(wǎng)站建設(shè)成都網(wǎng)站制作、網(wǎng)站營銷推廣、網(wǎng)站開發(fā)設(shè)計,對服務(wù)成都主動防護網(wǎng)等多個行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗。成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報價服務(wù),我們深知市場的競爭激烈,認(rèn)真對待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進步,是我們永遠的責(zé)任!

 
 
 
  1. function App() { 
  2.   const memoizedValue = useMemo( 
  3.     () => computeExpensiveValue(a, b), 
  4.     [a, b] 
  5.   ); 
  6.   // ... 

只有在依賴項改變后才會重新計算新的memoizedValue。

你有沒有想過,如果用useMemo緩存函數(shù)組件的返回值,會怎么樣呢?

舉個例子

我們有個全局context —— AppContext。

由于同學(xué)們偷懶,隨著項目的迭代,新增的context都選擇放在AppContext里,導(dǎo)致AppContext包含的內(nèi)容越來越多。

現(xiàn)在我們有個Tree組件,他會渲染一個很耗性能的大組件ExpensiveTree。

 
 
 
  1. function Tree() { 
  2.   let appContextValue = useContext(AppContext); 
  3.   let theme = appContextValue.theme; 
  4.  
  5.   return 

該組件內(nèi)部依賴AppContext中的theme狀態(tài)。

由于AppContext中包含很多與theme無關(guān)的state,導(dǎo)致每次其他無關(guān)的state更新,Tree都會重新render,進而ExpensiveTree組件也重新render。

現(xiàn)在這個優(yōu)化任務(wù)交到了你手上,該怎么辦呢?

優(yōu)化ExpensiveTree

這時候,useMemo就能派上用場:

 
 
 
  1. function Tree() { 
  2.   let appContextValue = useContext(AppContext); 
  3.   let theme = appContextValue.theme; 
  4.  
  5.   return useMemo(() => { 
  6.     return 
  7.   }, [theme]) 

我們將返回的ExpensiveTree作為useMemo返回值,theme作為依賴。

這樣,即使AppContext改變導(dǎo)致Tree反復(fù)render,ExpensiveTree也只會在theme改變后render。

[[380080]]

原理解析

要理解這么做有效的原因,需要了解三點:

  1. useMemo返回值是什么
  2. 函數(shù)組件的返回值是什么
  3. React組件在什么時候render

回答第一個問題:useMemo會將第一個參數(shù)(函數(shù))的返回值保存在組件對應(yīng)fiber中,只有在依賴項(第二個參數(shù))變化后才會重新調(diào)用第一個參數(shù)(函數(shù))計算一個新值。

回答第二個問題:函數(shù)組件的返回值是JSX對象。

同一個函數(shù)組件調(diào)用多次,返回的是多個「不同」的JSX對象(即使props未變,但JSX是新的引用)。

按照以上兩個回答,我們可以得出結(jié)論:

  • 以上useMemo用法實際上在函數(shù)組件對應(yīng)的fiber中緩存了一個完整的JSX對象

第三個問題,函數(shù)組件需要同時滿足如下條件才不會render:

1 oldProps === newProps

前后兩次更新props全等,注意是「全等」。

2 組件context沒有變化

3 workInProgress.type === current.type

組件更新前后fiber.type未變化,比如div沒有變?yōu)閜。

4 !includesSomeLane(renderLanes, updateLanes)

當(dāng)前fiber上不存在更新,或者存在更新但優(yōu)先級低。

  • 更詳細的解釋,可以參考這篇文章:React組件到底什么時候render?

當(dāng)我們不使用useMemo包裹返回值,每次Tree render返回的都是全新的JSX對象。

所以對于ExpensiveTree,oldProps !== newProps。

再看2:ExpensiveTree內(nèi)部context沒變,滿足

再看3:ExpensiveTree更新前后type都是ExpensiveTree,滿足

再看4: ExpensiveTree內(nèi)沒有狀態(tài)更新,滿足

所以,當(dāng)我們使用useMemo包裹ExpensiveTree后,當(dāng)theme不變,每次Treerender后返回的都是同一個JSX對象,滿足第一條。

基于這個原因,ExpensiveTree不會render。

總結(jié)

這篇文章提到的useMemo用法,并未在官網(wǎng)文檔中體現(xiàn),而是在#15156[1]中由Dan介紹。

相比Vue,React更靈活,開發(fā)過程中需要開發(fā)者注意更多細節(jié)。要完全了解React,可能需要學(xué)習(xí)一些源碼層面的知識。

參考資料

[1]#15156:

https://github.com/facebook/react/issues/15156#issuecomment-474590693


網(wǎng)頁題目:奇怪的useMemo知識增加了
URL標(biāo)題:http://uogjgqi.cn/article/ccsgihp.html
掃二維碼與項目經(jīng)理溝通

我們在微信上24小時期待你的聲音

解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流