useMemo和useCallback的用法和区别

2023-08-31
10304 分钟
...

介绍

useMemouseCallback是React中优化是常用的两个Hooks。它们有一些共同点,比如都需要传递一个依赖数组,只有当依赖项发生改变时才会更新数据。但是它们的使用场景一般不同,下面将具体分析两个Hooks的异同。

useMemo

useMemo的定义如下:

useMemo(factory, Dependencies)

其中factory是工厂函数, Dependencies是其所有依赖值的数组。

在组件初始化的时候会调用factory函数,并将返回值存储起来。当组件需要重新渲染时,react会首先依次判断每个依赖项的值是否发生了变化。如果没有变化,则直接使用之前的存储的返回值,而不会再次调用factory,如果依赖项发生变化,则会使用更新后的依赖项调用factory函数,返回最新的值。

这个Hooks的作用是能够避免一些消耗资源的运算,从而提高性能。下面是一个例子:

import React from 'react'
funtion MyComponent({n}) {
  // 返回斐波那契数列的第n项     
  function Fibonaccin){
    // ...     
  }     
  return    
  <div>    
    斐波那契数列的第{n}项是:{Fibonacci(n)}   
  </div> 
}

在上面这个组件中,每次组件重新渲染都会重新调用Fibonacci函数,即使n的值没有发生变化。这样如果n的值比较大的时候就会非常耗费性能,可以改为下面的写法。

import React, { useMemo } from 'react' 
funtion MyComponent({n}) {   
  // 返回斐波那契数列的第n项   
  function Fibonaccin){   
    // ...    
  }    
  const fibo = useMemo(() => Fibonacci(n), [n])  
  return      
  <div>       
    斐波那契数列的第{n}项是:{fibo}     
  </div> 
}

使用useMemo包裹后如果n的值没有发生变化,就不会重新调用Fibonacci函数,节约了性能。如果n的值足够大,节约的性能是非常可观的。

useCallback

useCallback的定义与useMemo类似:

useCallback(callback, Dependencies)

callback是一个函数对象,Dependencies是依赖项数组。

如果依赖项数组中的数据没有发生变化,则会返回上一次的callback函数。

默认情况下,每当一个组件中重新渲染,其中的函数都会重新声明。这样就会导致一个问题:如果该组件将这个函数传递给子组件,那么子组件也会重新渲染,但有时这样的渲染是不必要的。比如下面的例子:

import React from 'react'
funtion Parent(num) {    
  funtion handleClick(  ){   
    // 处理点击事件      
    console.log(num)    
  }  

  return     
  <div>                
    <Child onClick={()=>handleClick()} />   
  </div> 
}


每次父组件更新时,子组件也会重新渲染,无论子组件的内容是否发生了变化。如果需要优化可以改为下面的写法:

import React, { useCallback } from 'react' 
funtion Parent(num) {   
  const handleClick = useCallback(() => {     
    // 处理点击事件       
    console.log(num)   
  }, [num])
  // 只有当num发生改变时子组件接收到的回调函数才会发生变化 
  return        
  <div>          
    <Child onClick={()=>handleClick()}  />    
  </div> 
}

这样如果num的值没有发生变化,子组件接收到的回调函数就不会改变,也就不会因此触发渲染。

其他

其实useCallback就是useMemo的第一个参数的返回值是函数时的特殊情况,官方文档中也说明了使用useMemo来缓存一个函数与直接使用useCallback的效果是完全相同的,只是写法上会比较复杂,比如我们可以利用useMemo实现一个我们自己的useMyCallback:

fuction useMyCallback(callback, deps){  
  useMemo(() => () => callback, deps)
}

这样的效果和useCallback是完全相同的。

总结

useMemouseCallback都是用来优化性能的Hooks。本质上useCallback是对useMemo做了一层包装,作用都是通过判断依赖项是否改变来决定是否更新值,只不过useCallback的值是一个函数对象。

useMemo一般通过减少不必要的复杂计算来优化性能,useCallback一般用于给子组件传递回调函数时,减少子组件的渲染次数,从而优化性能。

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
react2025-12-02
useEffect与useLayoutEffect对比
在 React Hooks 中, 和 都用于处理副作用逻辑,例如订阅、事件监听、DOM 操作等。但它们有着本质性的执行时机差异,这影响到页面渲染、布局抖动、性能表现等关键点。 1\. 执行时机的核心区别 在 React 的渲染流程中: 1. 渲染(Render phase) React 根据 state/props 计算 UI,生成虚拟 DOM,不访问真实 DOM。 2. 提交(Commit phase) React 将虚拟 DOM 变...
学习
react2025-08-03
在 React 中实现倒计时功能会有什么坑
倒计时 倒计时是一个非常常见的业务场景,但是在 React 中实现起来,却不算简单。 首先我们来看这段倒计时代码,它能否正常执行? 来看看实际表现效果 可以看到计时器在不断执行,但是 的值却没有变。 这是一个很经典的问题:React 闭包陷阱 。 我们来详细分析下: 的依赖数组 是空的,这意味着 effect 只会在组件挂载时执行一次,而不会在 状态更新时重新执行。所以 回调函数中捕获的 值始终是初始值 。 这个问题解决起来也很简单,有...
学习面试
react2025-07-30
React性能优化三剑客:memo、useMemo和useCallback详解
前言 在React开发中,性能优化是一个永恒的话题。今天我们就来深入探讨React提供的三个重要性能优化工具: 、 和 ,它们如何帮助我们构建更高效的React应用。 1\. 为什么需要性能优化? 🤔 React的核心机制是当组件的state或props发生变化时,组件会重新渲染。但有时这种重新渲染是不必要的: 父组件更新导致所有子组件重新渲染 ,即使子组件的props没有变化 复杂计算在每次渲染时重复执行 ,消耗大量资源 函数引用在...
学习面试
react2025-06-05
React 中 useDeferredValue 和 startTransition 的核心区别与使用场景
React 中 和 ,两者都用于优化性能,但适用场景和实现方式不同。 核心概念解析 1\. useDeferredValue:延迟值更新 作用 :告诉 React 延迟更新某个值 ,直到所有高优先级渲染任务完成。 适用场景 :当某个值的更新会触发计算密集型渲染(如复杂列表、图表),但需要优先保证其他高优先级 UI(如输入框)的响应。 机制 : 保持旧值显示,后台计算新值。 计算完成后,用新值更新 UI,期间允许用户继续交互。 示例 :...
学习
react2024-12-18
Antd 样式覆盖
&nbsp; 目前作者所在的业务正在升级 Antd5.0,不得不说 Antd5.0 真的太香了,但是由于团队的 UE 规范进行了大改版,Antd5.0 所有的 必须对齐最新的规范,因此就需要对 Antd5.0 组件做主题定制。 现状 目前针对项目中使用的 antd 高频组件进行了梳理,并且根据规范基于 design token 对这些高频组件进行样式定制,对于主题色、圆角、边框、字体等用户 高的主题都已经满足团队规范。 虽然 Desig...
学习
react2024-12-06
React 19 终于发布,一大波新功能正式升级
这篇文章主要介绍了 React 19 的新功能,包括 Actions 自动处理数据突变相关状态,新增的 useActionState、useFormStatus、useOptimistic 等 hook,新的 use API 读取渲染资源,新的 React DOM 静态 API 生成静态站点,以及 React 服务器组件中的 RSC 和 RSA 等内容。同时提到后续会分享针对旧版功能的优化和改良。 关联问题: React 19 性能如何...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录