如何使用 useMemo 和 memo 优化 React 应用性能?

devtools/2025/1/20 14:19:15/

使用 useMemomemo 优化 React 应用性能

在构建复杂的 React 应用时,性能优化是确保应用流畅运行的关键。React 提供了多种工具来帮助开发者优化组件的渲染和计算逻辑,其中 useMemomemo 是两个非常有用的 Hook。本文将详细介绍这两个工具的使用方法及其应用场景。

1. useMemo 的介绍与使用

1.1 什么是 useMemo

useMemo 是一个 React Hook,用于记忆(缓存)某些计算结果,以避免不必要的重复计算。它接收两个参数:一个返回值的计算函数和一个依赖项数组。只有当依赖项发生变化时,useMemo 才会重新计算并返回新的值;否则,它将返回之前缓存的结果。

1.2 useMemo 的语法
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • computeExpensiveValue(a, b) 是一个计算昂贵值的函数。
  • [a, b] 是依赖项数组,只有当这些依赖项发生变化时,useMemo 才会重新执行计算。
1.3 示例:优化总价计算

在你的 Test2.tsx 组件中,total 函数用于计算商品的总价。每次组件重新渲染时,total 都会重新计算。为了优化这一点,我们可以使用 useMemo 来缓存计算结果:

import React, { useState, useMemo } from 'react';export default function Test2() {const [search, setSearch] = useState('');const [list, setList] = useState([{ id: 1, name: '苹果', price: 10, count: 1 },{ id: 2, name: '小米', price: 20, count: 1 },{ id: 3, name: '华为', price: 30, count: 1 },]);const handleAdd = (id: number) => {setList(list.map(item => item.id === id ? { ...item, count: item.count + 1 } : item));};const handleSub = (id: number) => {setList(list.map(item => item.count > 1 && item.id === id ? { ...item, count: item.count - 1 } : item));};// 使用 useMemo 缓存总价计算结果const total = useMemo(() => {return list.reduce((pre, cur) => pre + cur.price * cur.count, 0);}, [list]);return (<div><h1>父组件</h1><input type="text" value={search} onChange={(e) => setSearch(e.target.value)} /><table border={1} cellPadding={5} cellSpacing={0}><thead><tr><th>商品名称</th><th>商品价格</th><th>商品数量</th></tr></thead><tbody>{list.map(item => (<tr key={item.id}><td>{item.name}</td><td>{item.price * item.count}</td><td><button onClick={() => handleAdd(item.id)}>+</button><span>{item.count}</span><button onClick={() => handleSub(item.id)}>-</button></td></tr>))}</tbody><tfoot><tr><th scope="row" colSpan={1}>总价</th><td>{total}</td></tr></tfoot></table></div>);
}

在这个例子中,useMemo 确保只有当 list 发生变化时才会重新计算 total,从而减少了不必要的计算开销。

2. memo 的介绍与使用

2.1 什么是 memo

memo 是 React 提供的一个高阶组件(HOC),用于防止子组件不必要的重新渲染。它通过比较当前和上次渲染的 props 来决定是否需要重新渲染组件。如果 props 没有变化,则跳过渲染,直接复用之前的渲染结果。

2.2 memo 的语法
const MemoizedComponent = React.memo(MyComponent);
  • MyComponent 是你想要优化的组件。
  • React.memo 返回一个新的组件,该组件会在 props 没有变化时不重新渲染。
2.3 示例:优化子组件渲染

假设我们有一个子组件 ProductItem,它负责显示单个商品的信息。我们可以使用 memo 来优化这个组件,避免不必要的重新渲染:

import React from 'react';
import { memo } from 'react';interface ProductItemProps {product: { id: number; name: string; price: number; count: number };onAdd: () => void;onSub: () => void;
}const ProductItem: React.FC<ProductItemProps> = ({ product, onAdd, onSub }) => {console.log('ProductItem rendered');return (<tr key={product.id}><td>{product.name}</td><td>{product.price * product.count}</td><td><button onClick={onAdd}>+</button><span>{product.count}</span><button onClick={onSub}>-</button></td></tr>);
};// 使用 memo 包装 ProductItem 组件
const MemoizedProductItem = memo(ProductItem);export default MemoizedProductItem;

在这个例子中,MemoizedProductItem 只会在其 props 发生变化时重新渲染,否则会复用之前的渲染结果,从而提高性能。

3. useMemomemo 的区别

  • 作用范围

    • useMemo 用于优化组件内部的计算逻辑,减少不必要的计算。
    • memo 用于优化组件的渲染行为,减少不必要的重新渲染。
  • 使用场景

    • 当你在组件内部有复杂的计算逻辑时,可以使用 useMemo 来缓存计算结果。
    • 当你有一个子组件频繁重新渲染但实际内容没有变化时,可以使用 memo 来优化渲染性能。

4. 总结

useMemomemo 是 React 中非常强大的工具,能够显著提升应用的性能。合理使用它们可以帮助你避免不必要的计算和渲染,从而让应用更加高效和流畅。希望本文能帮助你更好地理解和使用这两个工具,为你的 React 应用带来更好的用户体验。


http://www.ppmy.cn/devtools/152108.html

相关文章

【Kotlin】上手学习之类型篇

一、类型 1.1 基本类型 主要分为 数字及其无符号版布尔字符字符串数组 1.1.1 数字 整数类型 Kotlin 提供了一组表示数字的内置类型。 对于整数&#xff0c;有四种不同大小的类型&#xff0c;因此值的范围也不同&#xff1a; 类型大小&#xff08;比特数&#xff09;最小…

Postman环境变量全局变量设置

在公司中&#xff0c;一般会存在开发环境、测试环境、线上环境等&#xff0c;如果需要在不 同的环境下切换做接口测试&#xff0c;显然我们需要把所有接口的域名进行修改&#xff0c;如果接 口测试用例较多&#xff0c;那么修改会非常费力&#xff0c;postman可直接通过切换环境…

数据库高可用方案-04-删除策略

数据库数据高可用系列 数据库高可用方案-01-数据库备份还原方案 数据库高可用方案-02-多机房部署 数据库高可用方案-03-主备等高可用架构 数据库高可用方案-04-删除策略 数据库高可用方案-05-备份与恢复 数据库高可用方案-06-监控与报警 数据库高可用方案-07-一致性校验…

【Spring Boot】掌握 Spring 事务:隔离级别与传播机制解读与应用

前言 &#x1f31f;&#x1f31f;本期讲解关于spring 事务传播机制介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话…

【Idea】编译Spring源码 read timeout 问题

Idea现在是大家工作中用的比较多的开发工具&#xff0c;尤其是做java开发的&#xff0c;那么做java开发&#xff0c;了解spring框架源码是提高自己技能水平的一个方式&#xff0c;所以会从spring 官网下载源码&#xff0c;导入到 Idea 工具并编译&#xff0c;但是发现build的时…

202509读书笔记|《飞花令·山》——两岸猿声啼不住,轻舟已过万重山

202509读书笔记|《飞花令山》——两岸猿声啼不住&#xff0c;轻舟已过万重山 《飞花令山》素心落雪编著&#xff0c;飞花令得名于唐代诗人韩翃《寒食》中的名句“春城无处不飞花”&#xff0c;类似于行酒令&#xff0c;是文人们的一种雅致的娱乐活动。 一直都比较喜欢看诗词&a…

leetcode刷题记录(四十八)——128. 最长连续序列

&#xff08;一&#xff09;问题描述 128. 最长连续序列 - 力扣&#xff08;LeetCode&#xff09;128. 最长连续序列 - 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。请你设计并实现时间复…

【Linux系统编程】—— 虚拟内存与进程地址空间的管理:操作系统如何实现内存保护与高效分配

文章目录 程序地址空间的概念虚拟地址与进程的关系进程地址空间进程地址空间的结构为什么使用虚拟内存(虚拟地址空间) 前言&#xff1a; 在现代操作系统中&#xff0c;进程的内存管理至关重要。操作系统通过虚拟地址空间来隔离不同进程的内存&#xff0c;确保它们不互相干扰&am…