当前位置: 首页 > news >正文

react useMemo Hook详解

什么是 useMemo Hook?

useMemo 是一个 React Hook,用于缓存计算结果,避免在每次组件渲染时重复执行昂贵的计算。它通过记忆计算的值,只有在依赖项变化时才会重新计算,从而优化性能。

简单来说,useMemo 让你的计算结果“记住”上一次的值,减少不必要的计算开销。


为什么需要 useMemo

在 React 函数组件中,每次渲染都会重新执行组件函数体。如果有复杂或耗时的计算(比如过滤大数组、复杂数学运算),每次渲染都重复计算会影响性能。

useMemo 解决了这个问题,通过缓存计算结果,只有当依赖的变量变化时才重新计算。

适用场景

  • 复杂的计算逻辑(比如处理大数据、排序、过滤)
  • 需要保持引用稳定的对象或数组(避免子组件不必要渲染)
  • 优化性能,减少重复计算

useMemo 的基本语法

useMemo 接收两个参数:

  1. 计算函数:返回你想缓存的值(可以是任何类型:数字、对象、数组等)。
  2. 依赖数组:控制何时重新计算,只有依赖项变化时才重新运行计算函数。

基本结构:

import { useMemo } from 'react';function MyComponent() {const memoizedValue = useMemo(() => {// 耗时计算逻辑return expensiveCalculation();}, [/* 依赖项 */]);return <div>{memoizedValue}</div>;
}
  • 返回值useMemo 返回缓存的计算结果(值),在依赖项不变的情况下,始终返回相同的引用。

useMemo 的使用场景

以下通过具体例子,带你理解 useMemo 的实际用途。

1. 优化昂贵计算

假设你有一个需要过滤和排序大数组的计算,useMemo 可以避免每次渲染都重复执行。

示例代码

import { useState, useMemo } from 'react';function FilterList() {const [numbers, setNumbers] = useState([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);const [filter, setFilter] = useState(5);// 使用 useMemo 缓存过滤结果const filteredNumbers = useMemo(() => {console.log('执行过滤计算');return numbers.filter(num => num > filter).sort((a, b) => b - a);}, [numbers, filter]); // 依赖 numbers 和 filterreturn (<div><inputtype="number"value={filter}onChange={e => setFilter(Number(e.target.value))}/><ul>{filteredNumbers.map(num => (<li key={num}>{num}</li>))}</ul></div>);
}

运行效果

  • filteredNumbers 是缓存的过滤和排序结果。
  • 只有当 numbersfilter 变化时,useMemo 才会重新计算(控制台打印“执行过滤计算”)。
  • 如果没有 useMemo,每次组件渲染(比如无关的状态变化)都会重新过滤和排序,浪费性能。

2. 保持对象或数组引用稳定(搭配 React.memo

如果一个对象或数组作为 props 传递给子组件,而子组件使用了 React.memo,每次渲染生成的新对象/数组会导致子组件重新渲染。useMemo 可以缓存对象/数组,保持引用稳定。

示例代码

import { useState, useMemo } from 'react';
import { memo } from 'react';// 子组件使用 React.memo
const ChildComponent = memo(({ config }) => {console.log('ChildComponent 渲染了');return <div>配置: {config.name}</div>;
});function ParentComponent() {const [count, setCount] = useState(0);// 使用 useMemo 缓存对象const config = useMemo(() => {return { name: '我的配置' };}, []); // 空数组,config 永不重新生成return (<div><p>计数: {count}</p><button onClick={() => setCount(count + 1)}>加1</button><ChildComponent config={config} /></div>);
}

运行效果

  • 点击“加1”按钮,count 变化,ParentComponent 重新渲染。
  • ChildComponent 不会重新渲染,因为 config 的引用(由 useMemo 缓存)没变。
  • 如果不用 useMemo,每次渲染都会生成新对象 { name: '我的配置' },导致 ChildComponent 不必要地重新渲染。

useMemo vs. 其他 Hooks

  • useCallback 的区别

    • useMemo 缓存计算结果(可以是任何值:对象、数组、数字等)。
    • useCallback 缓存函数,返回函数引用。
    • useCallback(fn, deps) 等价于 useMemo(() => fn, deps)
    // useMemo 缓存对象
    const memoizedValue = useMemo(() => ({ name: '小明' }), []);// useCallback 缓存函数
    const memoizedFn = useCallback(() => console.log('点击'), []);
    
  • useEffect 的关系

    • useMemo 用于缓存计算结果,避免重复计算。
    • useEffect 用于处理副作用(比如 API 请求、DOM 操作)。
    • 有时 useMemouseCallback 一起用于优化 useEffect 的依赖。

注意事项(新手常见坑)

  1. 不要滥用 useMemo

    • useMemo 本身有内存开销(缓存结果),只在计算昂贵或需要保持引用稳定时使用。
    • 如果计算很简单(比如 a + b),直接计算比用 useMemo 更高效。
  2. 依赖数组要正确填写

    • 确保依赖数组包含计算函数中用到的所有变量,否则可能导致 bug。
    • ESLint 的 react-hooks/exhaustive-deps 规则会帮你检查。
    const result = useMemo(() => {return expensiveCalculation(count); // count 必须在依赖数组中
    }, [count]);
    
  3. 引用稳定性不总是必要的

    • 如果子组件没用 React.memo,或计算结果不影响性能,可能不需要 useMemo
  4. 不要用 useMemo 替代所有状态

    • useMemo 是为优化计算设计的,不是状态管理工具。状态变化仍需用 useStateuseReducer

总结

  • useMemo 的作用:缓存计算结果,避免重复执行昂贵计算,保持引用稳定。
  • 使用场景
    • 优化复杂计算(比如过滤、排序大数据)。
    • 缓存对象/数组,配合 React.memo 避免子组件不必要渲染。
  • 语法useMemo(fn, deps),返回缓存的值,依赖项变化时重新计算。
  • 注意事项:只在需要时使用,正确声明依赖数组。
http://www.gsyq.cn/news/13993.html

相关文章:

  • Python技能大赛-备赛建议
  • github Connection reset by 20.205.243.160 port 443 fatal: Could not read from remote repository.
  • Vue 3.6 引入 Vapor Mode,虚拟DOM已死?
  • part 10
  • content和text方法的区别
  • 完整教程:从零开始学神经网络——前馈神经网络
  • 聪明的wyk
  • 论状压记忆化搜索
  • Spring Gateway动态路由实现方案 - 详解
  • 调用setState 之后发生了什么?
  • 树形dp [POI 2013] LUK-Triumphal arch
  • 万象EXCEL开发(三)格式解读calcChain.xml——东方仙盟练气期 - 指南
  • 使用 ShedLock 实现多实例定时任务单执行的常见错误及解决办法
  • PiXYZ Studio 2021下载地址与安装教程
  • 深入解析:在 C# .NETCore 中使用 MongoDB(第 2 部分):使用过滤子句检索文档
  • 深入解析:4、urbane-commerce 认证请求 DTO 设计规范
  • 选对强大的技术底座:一篇文章讲透虚拟机与容器核心差异
  • 深入解析:招聘:解决方案架构师 - 中国北京(混合办公)
  • 自然灾害vr学习机:山体滑坡+泥石流避险+洪涝逃生+地震逃生+台风避险+雷电避险 - 详解
  • 【面板材料】A股上市公司增发股票及配股相关资料(1991-2024年)
  • BindingList的应用与改进
  • 谷歌 SEO 新词 xx animate 等实操教程
  • 完整教程:【读书笔记】架构整洁之道 P6 实现细节
  • init.tcl
  • ffmpeg一些使用记录,防止忘记
  • 生产者-消费者问题
  • QAction的使用
  • flow.tcl
  • sg.测试 PySimpleGUI 取值方法
  • 剥开参数看本质:2025 年手机性能与处理器深度解析 - 详解