源码分析React中useCallback和useMemo

 更新时间:2026年04月01日 10:38:34   作者:Jinuss  
在React中,useCallback和useMemo用于优化性能,useCallback缓存函数,useMemo缓存函数返回值,它们将数据存放在fiber.memoizedState,若依赖未变,复用旧值,原理相似,useRef不绑定DOM,更新亦复用旧值,本文介绍React中useCallback和useMemo的相关知识,感兴趣的朋友一起看看吧

概述

在React中,useCallbackuseMemo分别用于缓存函数和变量,当其依赖没发生改变时,可以复用旧的函数或变量,一定程度上可以优化函数组件的性能。

源码分析

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;
}

总结

useCallbackuseMemo就是将函数和依赖存放在fiber.meomizedState的链表中。在函数组件重新渲染后,若依赖没有变化,就复用之前的旧值。若useRef这个hook的值不与DOM绑定,只是在函数组件内部使用,在函数组件更新后,也是复用旧值。它们的原理类似。

到此这篇关于源码分析React中useCallback和useMemo的文章就介绍到这了,更多相关React useCallback和useMemo内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • React中useEffect 与 useLayoutEffect的区别

    React中useEffect 与 useLayoutEffect的区别

    本文主要介绍了React中useEffect与useLayoutEffect的区别,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • 解决React报错Cannot assign to 'current' because it is a read-only property

    解决React报错Cannot assign to 'current'

    这篇文章主要为大家介绍了React报错Cannot assign to 'current' because it is a read-only property的解决方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • React内存泄漏的常见原因及避免策略

    React内存泄漏的常见原因及避免策略

    内存泄漏是指程序中分配的内存未能正确释放,导致内存占用不断增加,最终可能影响应用性能甚至崩溃,在React中,内存泄漏常发生于组件卸载后,本文将详细介绍内存泄漏在React中的常见原因及避免策略,需要的朋友可以参考下
    2025-03-03
  • react中setState的执行机制详解

    react中setState的执行机制详解

    setState() 的执行机制包括状态合并、批量更新、异步更新、虚拟 DOM 比较和渲染组件等步骤,这样可以提高性能并优化渲染过程,这篇文章主要介绍了react中的setState的执行机制,需要的朋友可以参考下
    2023-10-10
  • 工程级 React 注册登录全栈级流程分析

    工程级 React 注册登录全栈级流程分析

    这篇文章主要介绍了工程级 React 注册登录全栈级流程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • 使用react遍历对象生成dom

    使用react遍历对象生成dom

    这篇文章主要介绍了使用react遍历对象生成dom问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • styled-components 性能详解

    styled-components 性能详解

    这篇文章主要为大家介绍了styled-components 的性能示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • React实现路由鉴权的实例详解

    React实现路由鉴权的实例详解

    React应用中的路由鉴权是确保用户仅能访问其授权页面的方式,用于已登录或具有访问特定页面所需的权限,这篇文章就来记录下React实现路由鉴权的流程,需要的朋友可以参考下
    2024-07-07
  • 基于Cloud Studio构建React完成点餐H5页面(腾讯云 Cloud Studio 实战训练营)

    基于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)切换路由方法的区别及说明

    这篇文章主要介绍了react中history(push,go,replace)切换路由方法的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10

最新评论