源码分析React中useCallback和useMemo
概述
在React中,useCallback和useMemo分别用于缓存函数和变量,当其依赖没发生改变时,可以复用旧的函数或变量,一定程度上可以优化函数组件的性能。
源码分析
useCallback
- 挂载(首次渲染)
函数组件在挂载首次渲染时,useCallback调用的方法是mountCallback。
// callback 表示回调函数,deps是依赖数组,下同
function mountCallback(callback, deps) {
// 调用 mountWorkInProgress方法创建新的hook,并将其放到fiber的memoizedState链表上,最后返回新的hook
const hook = mountWorkInProgressHook();
// 判断依赖,若不存在,则为null
const nextDeps = deps === undefined ? null : deps;
// 将callback和deps 存放到fiber.memoizedState中,以便后续复用
hook.memoizedState = [callback, nextDeps];
// 最后返回callback
return callback;
}- 组件更新时
函数组件在更新时,hook的分发器dispatch会将useCallback指向updateCallback。
其源码实现如下:
function updateCallback(callback, deps) {
// 调用updateWorkInProgressHook读取旧Fiber的对应旧hook,以及复用旧hook,创建新hook并返回
const hook = updateWorkInProgressHook();
// 新的依赖取值
const nextDeps = deps === undefined ? null : deps;
// 从新hook上取hook之前数据
const prevState = hook.memoizedState;
// 若新依赖不等于null
if (nextDeps !== null) {
const prevDeps = prevState[1];
// 则判断新旧依赖是否发生了改变
if (areHookInputsEqual(nextDeps, prevDeps)) {
// 若没变化,则直接返回之前的callback
return prevState[0];
}
}
// 若新依赖不存在,或者新旧依赖不等,则再次将callback和deps依赖存入到fiber中
hook.memoizedState = [callback, nextDeps];
// 返回callback
return callback;
}useMemo
useMemo缓存的是回调函数的返回值,useCallback缓存的是回调函数,因此useMemo不过就是比useCallback的回调函数执行一次,并将其结果存到fiber.memoizedState的链表中,并返回;后续更新调度时,若依赖没发生改变,就读取旧hook中的值;若发生改变,再次执行回调函数,将它的返回值存起来,同时返回即可。
其源码实现如下:
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;
}总结
useCallback和useMemo就是将函数和依赖存放在fiber.meomizedState的链表中。在函数组件重新渲染后,若依赖没有变化,就复用之前的旧值。若useRef这个hook的值不与DOM绑定,只是在函数组件内部使用,在函数组件更新后,也是复用旧值。它们的原理类似。
到此这篇关于源码分析React中useCallback和useMemo的文章就介绍到这了,更多相关React useCallback和useMemo内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
- React中useMemo、useCallback的具体使用
- React Hooks之使用useCallback和useMemo进行性能优化方式
- 详解React中的useMemo和useCallback的区别
- React中memo useCallback useMemo方法作用及使用场景
- React源码分析之useCallback与useMemo及useContext详解
- React 中 memo useMemo useCallback 到底该怎么用
- react性能优化useMemo与useCallback使用对比详解
- React 正确使用useCallback useMemo的方式
- react组件memo useMemo useCallback使用区别示例
- React useMemo和useCallback的使用场景
相关文章
React中useEffect 与 useLayoutEffect的区别
本文主要介绍了React中useEffect与useLayoutEffect的区别,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2021-07-07
解决React报错Cannot assign to 'current'
这篇文章主要为大家介绍了React报错Cannot assign to 'current' because it is a read-only property的解决方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2022-12-12
基于Cloud Studio构建React完成点餐H5页面(腾讯云 Cloud Studio 实战训练营)
最近也是有机会参与到了腾讯云举办的腾讯云Cloud Studio实战训练营,借此了解了腾讯云Cloud Studio产品,下面就来使用腾讯云Cloud Studio做一个实战案例来深入了解该产品的优越性吧,感兴趣的朋友跟随小编一起看看吧2023-08-08
react中history(push,go,replace)切换路由方法的区别及说明
这篇文章主要介绍了react中history(push,go,replace)切换路由方法的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2023-10-10


最新评论