react组件放在数组中_为什么要在函数组件中使用React.memo?
這里提一下,如果大家看到這個標(biāo)題有所疑惑的話,可以花點時間看一下本篇文章。反之呢如果是看到標(biāo)題第一時間就反映出結(jié)論的話,就可以去get其他文章的知識點了
那么接下來就不廢話了,直接長刀直入,進(jìn)入正題!
初探memo
首先讓我們用一個例子走進(jìn)React.memo的世界
呆呆的函數(shù)組件 - 沒有使用memo
對于一個函數(shù)組件來說,如果沒有使用React.memo就好比是一個人沒有腦子,就笨笨的呆呆的
不信我們就來看下面的Demo
點擊訪問演示Demo
讓我們來分析下上圖發(fā)生的流程:
那么問題就來了,按正常邏輯來說,應(yīng)該是這樣的流程才對:
but理想異常豐滿的,現(xiàn)實十分骨干的。 事實就是不但App組件發(fā)生了更新,B組件也跟著進(jìn)行了更新,這不是我們想要的,因為對于B組件來說:明明老子啥都沒干,卻還非要我再重新穿一遍衣服?
無效渲染的原因
那么造成無效渲染的原因是啥呢?
其實簡單說來是這樣的:
函數(shù)組件本身沒有識別prop值的能力,每次父組件更新的時候都相當(dāng)于是給子組件一個新的prop值。所以就相當(dāng)于B組件這小子因為沒帶腦子(React.memo),是個呆呆的二傻子,所以他做為一個普通組件,就沒有分別prop的能力,當(dāng)他看到別人都更新了也就跟著把自己也造了一遍,因此就會造成上面中的問題。
給憨憨帶上腦子 - 使用memo進(jìn)行包裹
給函數(shù)組件帶上腦子 當(dāng)我們給一個函數(shù)組件帶上腦子的時候,就想下面這樣
import React form 'react';const FuncComponent = ()=>{return火熱很火辣
}export default React.memo(FunComponent);就不會發(fā)生上面那種,無腦render組件的情況了
試著把上面demo中B組件代碼里最后一行的注釋放開試一下吧
然后像上面一樣再次點擊一下按鈕,看看控制臺的打印結(jié)果:
Yep! 只更新了App組件,符合預(yù)期!
那么到底是為什么造成的這種原因呢
所以到這里還不算完,讓我們進(jìn)一步升溫
激情升溫 - 深入探索
到這里其實我們還是不太清楚memo是怎么做到避免無效更新的,接下來我們就來扒一扒!
class組件中的性能優(yōu)化點
不知道大家有沒有發(fā)現(xiàn)class組件中也有一個這樣作用的東西,叫做PureComponent,它的功能和memo是一毛一樣的。
來回顧一下,我們在class組件中經(jīng)常用到的寫法:
import React, {PureComponent} from 'react';class Demo extends PureComponent {// 性能優(yōu)化點shouldComponentUpdate(nextProps, nextState){// 默認(rèn)始終返回truereturn true; }render() {return聽懂掌聲
}}總的來說其實PureComponnet和memo都是通過對props值的淺比較來決定該組件是否需要更新的。
如果我們在class組件中,不主動使用PureComponent,也可以手動的去決定該組件是否更新,具體做法:
在生命周期shouldComponentUpdate,來通過對當(dāng)前porps以及state值的對比,然后返回一個布爾值(true或者false)來決定該組件是否更新。
其實PureComponent組件就是把這對比值的部分功能幫我們完成了,方便我們直接使用,而不用再去手動的去寫代碼進(jìn)行類似的優(yōu)化。
memo的功能實現(xiàn)
這里是我的猜想哈,memo的原理和PureComponent應(yīng)該是一樣的,從開發(fā)者的角度去想,既然class組件有這樣一個優(yōu)化方法,那既然要推行Hook,函數(shù)組件也必定需要一個類似功能的方法去幫助大家減少代碼優(yōu)化的工作量。所以感覺兩者在功能的實現(xiàn)上應(yīng)該大部分都是一致的。 這里也放上一段React中PureComponent進(jìn)行淺比較的代碼,方便大家進(jìn)一步理解
function shallowEqual (objA: mixed, objB: mixed): boolean { // 這里的is是判斷兩個值是否相等,只不過是對 + 0 和 - 0,以及 NaN 和 NaN 的情況進(jìn)行了特殊的處理封裝,目前react源碼中好像有一套新的is判斷 if (is (objA, objB)) { return true; } // 判斷是否為對象類型 if ( typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null ) { return false; } // 比較兩個對象的,屬性數(shù)量是否相等 const keysA = Object.keys (objA); const keysB = Object.keys (objB); if (keysA.length !== keysB.length) { return false; } // 比較兩個對象的的屬性是否相等,值是否相等 for (let i = 0; i < keysA.length; i++) { if ( !hasOwnProperty.call (objB, keysA [i]) || !is (objA [keysA [i]], objB [keysA [i]]) ) { return false; } } return true;}這就是react中進(jìn)行淺層比較的源碼,也是PureComponent和memo決定是否更新組件的重要依據(jù)。
memo配合useMemo、useCallback
一般在項目的優(yōu)化實踐中,memo包裹的函數(shù)組件都是要配合useMemo和useCallback來使用的
對于useMemo和useCallback其實我不準(zhǔn)備長篇大幅的講述了,因為社區(qū)已經(jīng)有很多不錯的文章了,大家可以搜來看一下。 我這里只做一個說人話的簡單介紹就好了
useCallback
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );返回值是一個函數(shù)(memoizedCallback),這個函數(shù)就是作為第一個參數(shù)傳進(jìn)去的那個。區(qū)別就是作為返回值的這個函數(shù)是一個memoized的版本,用人話理解就是:保持了函數(shù)的引用。不會在組件更新時,去重新聲明函數(shù),從而改變在內(nèi)存中的引用地址。
除非是第二個參數(shù)數(shù)組里的依賴項發(fā)生改變,否則這個做為返回值的函數(shù)(memoizedCallback)就一直保持原先的狀態(tài)
應(yīng)用場景
經(jīng)常使用在父組件A向子組件B傳遞一個函數(shù)作為prop值的時候
父組件A:
import React,{ useCallback } form 'react';const A = () => {return ( // 如果不使用useCallback包裹的話,每次A的更新,都會重新聲明這個handleClick的這個函數(shù),導(dǎo)致B組件無效的更新 //doSomething,[x,xx]) }; );}export default A;子組件B:
import React,{ memo } form 'react';const B = (props) => {const { handleClick } = props;return 卑微小B在線被Diss;}// 這里需要注意,要配合memo使用,否則的話不帶腦子的B組件會始終認(rèn)為傳遞過來的prop值都是一個全新的export default memo(B);useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);其實和useCallback很像,只不過是useMemo返回的是一個值,而不是一個函數(shù)
useCallback 的第一個參數(shù)是函數(shù),這個函數(shù)的返回值會作為useMemo的返回值memoizedValue)
除非是第二個參數(shù)數(shù)組里的依賴項發(fā)生改變,否則這個做為返回值(memoizedValue)就一直保持原先的值
useCallback能做的事useMemo都能做,但是還是推薦各司其職
const fn = useCallback( () => //doSomething , [x,xx])// 相當(dāng)于const fn = useMemo( ()=> () => //doSomething , [x,xx])// 因為useMemo的返回值是第一個函數(shù)的返回值,所以只要讓第一個參數(shù)的函數(shù)返回一個函數(shù)就可以達(dá)到useCallback的效果結(jié)尾 需要這些資料,可以私信 666 領(lǐng)取
總結(jié)
以上是生活随笔為你收集整理的react组件放在数组中_为什么要在函数组件中使用React.memo?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql网络安装教程_详细教程--My
- 下一篇: hashmap时间和空间复杂度_Pyth