源碼分析React中useCallback和useMemo
概述
在React中,useCallback和useMemo分別用于緩存函數(shù)和變量,當(dāng)其依賴沒發(fā)生改變時(shí),可以復(fù)用舊的函數(shù)或變量,一定程度上可以優(yōu)化函數(shù)組件的性能。
源碼分析
useCallback
- 掛載(首次渲染)
函數(shù)組件在掛載首次渲染時(shí),useCallback調(diào)用的方法是mountCallback。
// callback 表示回調(diào)函數(shù),deps是依賴數(shù)組,下同
function mountCallback(callback, deps) {
// 調(diào)用 mountWorkInProgress方法創(chuàng)建新的hook,并將其放到fiber的memoizedState鏈表上,最后返回新的hook
const hook = mountWorkInProgressHook();
// 判斷依賴,若不存在,則為null
const nextDeps = deps === undefined ? null : deps;
// 將callback和deps 存放到fiber.memoizedState中,以便后續(xù)復(fù)用
hook.memoizedState = [callback, nextDeps];
// 最后返回callback
return callback;
}- 組件更新時(shí)
函數(shù)組件在更新時(shí),hook的分發(fā)器dispatch會(huì)將useCallback指向updateCallback。
其源碼實(shí)現(xiàn)如下:
function updateCallback(callback, deps) {
// 調(diào)用updateWorkInProgressHook讀取舊Fiber的對(duì)應(yīng)舊hook,以及復(fù)用舊hook,創(chuàng)建新hook并返回
const hook = updateWorkInProgressHook();
// 新的依賴取值
const nextDeps = deps === undefined ? null : deps;
// 從新hook上取hook之前數(shù)據(jù)
const prevState = hook.memoizedState;
// 若新依賴不等于null
if (nextDeps !== null) {
const prevDeps = prevState[1];
// 則判斷新舊依賴是否發(fā)生了改變
if (areHookInputsEqual(nextDeps, prevDeps)) {
// 若沒變化,則直接返回之前的callback
return prevState[0];
}
}
// 若新依賴不存在,或者新舊依賴不等,則再次將callback和deps依賴存入到fiber中
hook.memoizedState = [callback, nextDeps];
// 返回callback
return callback;
}useMemo
useMemo緩存的是回調(diào)函數(shù)的返回值,useCallback緩存的是回調(diào)函數(shù),因此useMemo不過就是比useCallback的回調(diào)函數(shù)執(zhí)行一次,并將其結(jié)果存到fiber.memoizedState的鏈表中,并返回;后續(xù)更新調(diào)度時(shí),若依賴沒發(fā)生改變,就讀取舊hook中的值;若發(fā)生改變,再次執(zhí)行回調(diào)函數(shù),將它的返回值存起來,同時(shí)返回即可。
其源碼實(shí)現(xiàn)如下:
function mountMemo(
nextCreate,
deps,
): T {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
function updateMemo(
nextCreate,
deps,
) {
const hook = updateWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const prevState = hook.memoizedState;
if (nextDeps !== null) {
const prevDeps = prevState[1];
if (areHookInputsEqual(nextDeps, prevDeps)) {
return prevState[0];
}
}
const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}總結(jié)
useCallback和useMemo就是將函數(shù)和依賴存放在fiber.meomizedState的鏈表中。在函數(shù)組件重新渲染后,若依賴沒有變化,就復(fù)用之前的舊值。若useRef這個(gè)hook的值不與DOM綁定,只是在函數(shù)組件內(nèi)部使用,在函數(shù)組件更新后,也是復(fù)用舊值。它們的原理類似。
到此這篇關(guān)于源碼分析React中useCallback和useMemo的文章就介紹到這了,更多相關(guān)React useCallback和useMemo內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- React中useMemo和useCallback的使用小結(jié)
- React中useMemo、useCallback的具體使用
- 詳解React中的useMemo和useCallback的區(qū)別
- React中useCallback useMemo使用方法快速精通
- React中useCallback useMemo到底該怎么用
- 解析React中useMemo與useCallback的區(qū)別
- react性能優(yōu)化useMemo與useCallback使用對(duì)比詳解
- react組件memo useMemo useCallback使用區(qū)別示例
- React useMemo和useCallback的使用場(chǎng)景
- React中useMemo 和 useCallback 的區(qū)別小結(jié)
相關(guān)文章
react+antd.3x實(shí)現(xiàn)ip輸入框
這篇文章主要為大家詳細(xì)介紹了react+antd.3x實(shí)現(xiàn)ip輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
react實(shí)現(xiàn)路由動(dòng)畫跳轉(zhuǎn)功能
這篇文章主要介紹了react路由動(dòng)畫跳轉(zhuǎn)功能,大概思路是下載第三方庫?引用,創(chuàng)建css文件引用,想要實(shí)現(xiàn)跳轉(zhuǎn)動(dòng)畫功能,就在那個(gè)組件的根節(jié)點(diǎn)綁定classname屬性即可,在跳轉(zhuǎn)的時(shí)候即可實(shí)現(xiàn),需要的朋友可以參考下2023-10-10
React通過useContext特性實(shí)現(xiàn)組件數(shù)據(jù)傳遞
本文主要介紹了React如何通過useContext特性實(shí)現(xiàn)組件數(shù)據(jù)傳遞,文中有相關(guān)的代碼示例供大家參考,對(duì)我們學(xué)習(xí)React有一定的幫助,需要的朋友可以參考下2023-06-06

