目錄
React.memo
useCallback
useMemo
React.memo
React組件會在兩種情況下下發(fā)生渲染
第一種:當(dāng)組件自身的state發(fā)生變化時
第二種:當(dāng)組件的父組件重新渲染時
第一種情況下重新渲染無可厚非,state都變化了組件自然應(yīng)該重新進(jìn)行渲染,但是第二種情況似乎并不是總怎么必要,有時候僅僅只需要父組件重新渲染即可,但是其子組件也跟著渲染,如果是很復(fù)雜的邏輯的話,子組件再渲染一遍就會造成資源的浪費(fèi),有什么方法能杜絕這種情況呢?
React.memo()是一個高階組件,它接收另一個組件作為參數(shù),并且會返回一個包裝過的新組件,包裝過的新組件就會具有緩存作用,包裝過后,只有組件的props發(fā)生變化時,才會觸發(fā)組件的重新渲染,否則總是返回緩存中結(jié)果。
如下在父組件App中調(diào)用子組件A,在子組件A中調(diào)用孫組件B,在每個組件當(dāng)中都打印標(biāo)識組件渲染的證明,并且在后代組件中使用React.memo,防止組件的重新渲染,具體的實(shí)現(xiàn)過程如下圖所示實(shí)現(xiàn)的過程。
接下來我會將組件渲染的過程一一記錄下來,大家仔細(xì)看看加入了React.memo后,組件渲染會發(fā)生何種變化:
可以看到初次渲染時,所有的組件都會被執(zhí)行一次,? 當(dāng)點(diǎn)擊按鈕時,父組件傳遞給子組件A的props值發(fā)生變化導(dǎo)致A組件又被重新渲染一次,接下來僅僅是父組件發(fā)生變化,當(dāng)父組件的值為4的時候會再次導(dǎo)致子組件A的props值發(fā)生變化導(dǎo)致子組件A再次被重新渲染,因?yàn)閷O組件B沒有被傳入props,導(dǎo)致其只有在初次渲染的時候被被渲染,后面即使父組件發(fā)生變化,其也不會重新渲染,具體的過程如上圖所示。
useCallback
useCallback這個API作用也是阻止組件渲染的,不知道大家有沒有設(shè)想過這樣一個場景,當(dāng)子組件調(diào)用父組件的方法去修改父組件身上的值的時候,子組件會不會重新被渲染,答案是會的。在知道這個原因的前提下,你應(yīng)該要明白什么是重新渲染,重新渲染就是整個組件的代碼會被重新執(zhí)行一次,也就是說父組件修改其本身數(shù)值的方法也會被重新執(zhí)行,這就導(dǎo)致了通過props傳遞給子組件其修改父組件的方法被重新執(zhí)行變化了,導(dǎo)致子組件會被再一次被重新渲染,也就是說子組件的頁面沒有發(fā)生任何變化,但是子組件仍被重新渲染了,因此不管是用不用上面講解的React.memo方法,子組件都會被重新渲染,具體效果如下:
有沒有辦法能夠解決這個問題呢?這就要使用useCallback這個API來解決這個辦法了。
useCallback是一個鉤子函數(shù),用來創(chuàng)建React中的回調(diào)函數(shù),創(chuàng)建的回調(diào)函數(shù)不會總在組件重新渲染時重新創(chuàng)建,具體實(shí)現(xiàn)過程如下:
下圖很明顯,第一次創(chuàng)建時所有組件都會渲染一次,當(dāng)修改父組件的值時,使用usecallback之后,其函數(shù)不會再被重新創(chuàng)建,這也就讓其子組件不會再被重新渲染,完美解決問題。
useMemo
上面兩個方法都是講解組件與組件之間減少渲染的次數(shù),那么組件自身能不能減少渲染的范圍呢?要知道我們一旦對當(dāng)前組件進(jìn)行數(shù)值修改,當(dāng)前組件就會被重新渲染,也就是說當(dāng)前組件的所有代碼都會被再次執(zhí)行一次,但是再某種場景下,我僅僅是想修改當(dāng)前組件某一處的數(shù)值,并沒有想修改整個組件,但是整個組件都給我渲染一遍,這種是不是也會造成資源的浪費(fèi),給出如下情景:
import React, { useState } from 'react'
const sumFun = (a,b) =>{
console.log('函數(shù)被重新執(zhí)行了');
return a + b
}
const App = () => {
const [count,setCount] = useState(0)
const sum = sumFun(12,14)
const addHandler = () =>{
setCount(prevState => prevState + 1)
}
return (
<div>
<h2>當(dāng)前函數(shù)的和為:{sum}</h2>
<h3>App根組件--當(dāng)前值為:{count}</h3>
<button onClick={addHandler}>點(diǎn)擊+1</button>
</div>
)
}
export default App
我僅僅是想增加當(dāng)前組件的值,而函數(shù)是寫死的,就是渲染一個數(shù)值而已,但是其被迫跟著整個組件重新渲染了,結(jié)果如下:
讓我們設(shè)想這樣一個場景:sumFun函數(shù)冤枉的說:我啥也沒干你憑啥讓我再重新執(zhí)行一次,我: 讓你執(zhí)行就執(zhí)行,廢什么話,隨大流懂不懂,sumFun怒氣沖沖的說:這可是你說的,你不仁別怪我不義了,sumFun懷恨在心打出以下函數(shù):
由于sumFun函數(shù)的騷操作,導(dǎo)致整個組件的運(yùn)行被sumFun一人給阻塞掉了,必須等待sumFun執(zhí)行完成,整個組件才會被重新渲染,一個人有問題了,整個組件都需要等待他,這就很被動了,于是我說:sumFun快收了神通吧,有沒有啥辦法能夠解決它啊
接下來開始useMemo登場使用,給出如下代碼:
import React, { useState,useMemo } from 'react'
const sumFun = (a,b) =>{
const begin = Date.now() // 獲取當(dāng)前的時間戳
while(1){
if(Date.now() - begin > 3000){ // 死循環(huán),必須讓其等待三秒才break出去跳出循環(huán)
break
}
}
console.log('函數(shù)被重新執(zhí)行了');
return a + b
}
const App = () => {
const [count,setCount] = useState(0)
let a = 100
let b = 120
if(count % 10 === 0){
a+=count
}
const sum = useMemo(()=>{
return sumFun(a,b)
},[a,b])
const addHandler = () =>{
setCount(prevState => prevState + 1)
}
return (
<div>
<h2>當(dāng)前函數(shù)的和為:{sum}</h2>
<h3>App根組件--當(dāng)前值為:{count}</h3>
<button onClick={addHandler}>點(diǎn)擊+1</button>
</div>
)
}
export default App
由于sumFun被useMemo包裹,這就導(dǎo)致其只有在a和b發(fā)生變化時才會被重新渲染,如下:
文章來源:http://www.zghlxwxcb.cn/news/detail-420521.html
并不是以后的項(xiàng)目都需要限制重新渲染,代碼邏輯簡單組件功能少的完全是沒必要的,影響極小,只要在特別情況下或者說項(xiàng)目復(fù)雜要追求效率的場景下,渲染限制組件重新渲染獲取是一個不錯的選擇。文章來源地址http://www.zghlxwxcb.cn/news/detail-420521.html
到了這里,關(guān)于React--》React組件變化每次都會導(dǎo)致重新渲染,如何解決?的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!