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

React useMemo(当依赖项未变化,重复渲染时直接返回上一次缓存计算结果,而非重新执行计算)

文章目录

  • React `useMemo` 介绍:提升组件性能的关键利器
    • 1. `useMemo` 是什么?
      • 基本语法
    • 2. 为什么需要 `useMemo`?
      • 场景一:昂贵计算
      • 场景二:避免子组件不必要渲染
      • 场景三:稳定引用(如避免 useEffect 重复触发)
  • 3. 在 Next.js App Router 中使用 useMemo(示例)
    • 下面示例基于 **Next.js 13+ App Router**,展示如何在页面组件中使用 `useMemo` 来处理 expensive computation。
      • 📁 项目结构
      • 📄 `app/page.tsx`
      • 🔍 代码解析
    • 下面是去掉useMemo的版本,我们来看看是什么情况
  • 4. 使用 useMemo 的注意事项
      • ❗不要过度使用 useMemo
      • ❗依赖项一定要正确填写
      • ✔ 最佳实践
  • 5. 总结

React useMemo 介绍:提升组件性能的关键利器

在 React 开发中,组件渲染性能是一个永恒的话题。当组件包含复杂计算、依赖重的派生数据,或在高频渲染场景中运行时,就会带来性能下降。这时,React 提供的 useMemo 就能发挥重要作用——用于缓存计算结果,避免不必要的重复运算,从而提升应用性能。

1. useMemo 是什么?

useMemo 是 React 的一个 Hook,用于缓存某个计算过程的结果(memoized value)。其核心思想是:

当依赖项未变化时,重复渲染时直接返回上一次的计算结果,而不是重新执行计算。

基本语法

const memoizedValue = useMemo(() => {return expensiveComputation(a, b);
}, [a, b]);
  • 第一个参数是返回计算结果的函数。
  • 第二个参数是依赖项数组,当依赖项变化时会重新执行计算。

2. 为什么需要 useMemo

场景一:昂贵计算

例如需要处理大量数据、复杂筛选或排序逻辑,如果每次渲染都触发,会导致卡顿。

场景二:避免子组件不必要渲染

当 memoized 值作为 props 传递给子组件时,如果不使用 useMemo,每次渲染都会生成新引用,从而导致子组件重新渲染。

场景三:稳定引用(如避免 useEffect 重复触发)


3. 在 Next.js App Router 中使用 useMemo(示例)

下面示例基于 Next.js 13+ App Router,展示如何在页面组件中使用 useMemo 来处理 expensive computation。

📁 项目结构

app/page.tsx

📄 app/page.tsx

"use client";import { useMemo, useState } from "react";export default function HomePage() {const [count, setCount] = useState(0);const [query, setQuery] = useState("");// 模拟昂贵计算(比如过滤大型数据列表)const filteredList = useMemo(() => {console.log("执行 expensive computation...");const data = Array.from({ length: 50000 }, (_, i) => `Item ${i}`);return data.filter((item) => item.includes(query));}, [query]);return (<main style={{ padding: 20 }}><h1>React useMemo 示例(Next.js App Router)</h1><div style={{ marginTop: 20 }}><inputvalue={query}onChange={(e) => setQuery(e.target.value)}placeholder="输入查询关键字(触发 expensive computation)"style={{ padding: 8, width: 300 }}/></div><div style={{ marginTop: 20 }}><buttononClick={() => setCount(count + 1)}style={{ padding: "6px 12px" }}>点击计数:{count}</button></div><div style={{ marginTop: 20 }}><h3>过滤结果({filteredList.length} items)</h3><ul>{filteredList.slice(0, 20).map((item) => (<li key={item}>{item}</li>))}</ul><small>(仅显示前 20 条)</small></div></main>);
}

在这里插入图片描述

在这里插入图片描述

在输入框输入会触发console.log("执行 expensive computation..."); 打印,点击计数不会,这样就避免了不必要的大规模计算

🔍 代码解析

  • filteredList 依赖 query,当 query 改变时才会重新执行过滤。
  • 点击“计数”按钮只修改 count,不触发 expensive computation。
  • 控制台可以观察到 expensive computation... 打印次数明显减少。

下面是去掉useMemo的版本,我们来看看是什么情况

// app/page.tsx (Next.js 13 app-router, client component)"use client";import { useState } from "react"; // 移除了 useMemo 导入export default function HomePage() {const [count, setCount] = useState(0);const [query, setQuery] = useState("");// 直接计算而不使用 useMemo(每次渲染都会重新执行)console.log("执行 expensive computation..."); // 注意:这条日志会在每次渲染时触发const data = Array.from({ length: 50000 }, (_, i) => `Item ${i}`);const filteredList = data.filter((item) => item.includes(query));return (<main style={{ padding: 20 }}><h1>React useMemo 示例(Next.js App Router)</h1><div style={{ marginTop: 20 }}><inputvalue={query}onChange={(e) => setQuery(e.target.value)}placeholder="输入查询关键字(触发 expensive computation)"style={{ padding: 8, width: 300 }}/></div><div style={{ marginTop: 20 }}><buttononClick={() => setCount(count + 1)}style={{ padding: "6px 12px" }}>点击计数:{count}</button></div><div style={{ marginTop: 20 }}><h3>过滤结果({filteredList.length} items)</h3><ul>{filteredList.slice(0, 20).map((item) => (<li key={item}>{item}</li>))}</ul><small>(仅显示前 20 条)</small></div></main>);
}

在这里插入图片描述

发现点击计数也会触发console.log("执行 expensive computation..."); 打印,相当于下面代码也被执行,非常耗资源:

const data = Array.from({ length: 50000 }, (_, i) => `Item ${i}`);
const filteredList = data.filter((item) => item.includes(query));

4. 使用 useMemo 的注意事项

❗不要过度使用 useMemo

过度缓存会带来额外内存和计算开销,如果计算量很小,反而得不偿失。

❗依赖项一定要正确填写

依赖项写错会导致:

  • 缓存不更新(bug)
  • 每次都重新执行(性能浪费)

✔ 最佳实践

  • 用于昂贵计算(排序、过滤、格式化大型数据)
  • 用于稳定引用(如传给 memoized 子组件)
  • 用于避免 useEffect 不必要触发

5. 总结

useMemo 是 React 提供的重要性能优化工具,适用于缓存昂贵计算或保持引用稳定。在 Next.js App Router 中,它和普通的 React 组件用法完全一致,但要注意不要滥用。

在真实项目中,合理应用 useMemo 可以显著提高渲染性能,让页面更加流畅。

http://www.dtcms.com/a/618104.html

相关文章:

  • 【IOS开发】Objective-C 与 Swift 的对比
  • 在STM32 HAL库中使用 WFI 实现低功耗准确延时
  • 编程语言落地手册:erlang实现与汇编剖析
  • 搜索下单(es、mysql、MQ同步;关于事务失效)
  • aleph-node Node upgrade instructions 节点升级说明
  • 找谁做网站网站建设与运营培训班
  • 智能制造与工业4.0:5G与物联网的深度融合
  • GSV1201S(2201S)#ACP@支持 DisplayPort 1.2 到 HDMI 1.4 转换且集成嵌入式 MCU
  • Linux SPI 驱动实验
  • 【开题答辩全过程】以 基于Java的水族馆销售与经营管理系统的设计与实现为例,包含答辩的问题和答案
  • 网站响应是什么问题吗最近国际时事
  • 从拟南芥到线虫:我的生物信息学多组学实操笔记
  • 指尖革命!2025输入法生态位深度测评:智能,远不止于输入!
  • 如何在Windows系统上安装和配置Node.js及Node版本管理器(nvm)
  • 网站开发 保证书旅游网站制作分析
  • Docker实战深度解析:从Nginx部署到私有镜像仓库管理
  • 读书笔记|算法的破坏性影响
  • 网站制作需要平台企业网站的切片怎么做
  • 数据结构与算法工程笔记:决策树/sstable与性能优化
  • Linux 服务器配置 rootless docker Quick Start
  • LTE/5G L3 RRC层技术介绍
  • C语言进阶知识--文件操作
  • 网站建设需要哪些资料扶贫网站建设方案
  • C++标准模板库(STL)——list的模拟实现
  • 幽冥大陆(二十二)dark语言智慧农业电子秤读取——东方仙盟炼气期
  • 5.驱动led灯
  • RTL8367RB的国产P2P替代方案用JL6107-PC的可行性及实现方法
  • <MySQL——L1>
  • 有没有网站做字体变形自学软装设计该怎么入手
  • 做网站咸阳贵州省建设厅城乡建设网站