使用 useMemo 和 React.memo 优化 React 组件渲染

在 React 中,性能优化是一个重要的主题,特别是在复杂的组件树中。本文将演示如何在同一个父组件中使用 useMemoReact.memo 来优化子组件的渲染。

1. 组件结构

创建一个父组件,包含两个子组件:

  • MemoChild: 使用 React.memo 进行优化。
  • ExpensiveChild: 使用 useMemo 缓存。

示例:

javascript 复制代码
import React, { useState, useMemo } from 'react';

// 子组件,使用 React.memo
const MemoChild = React.memo(({ data }) => {
  console.log('MemoChild rendered');
  return <div>{data}</div>;
});

// 子组件,使用 useMemo 缓存
const ExpensiveChild = ({ data }) => {
  console.log('ExpensiveChild rendered');
  return <div>{data}</div>;
};

// 父组件
function Parent() {
  const [count, setCount] = useState(0);
  const [data, setData] = useState('Initial Data');

  // 使用 useMemo 来缓存 ExpensiveChild
  const memoizedExpensiveChild = useMemo(() => {
    console.log('Calculating ExpensiveChild');
    return <ExpensiveChild data={data} />;
  }, [data]);

  return (
    <div>
      <h1>Parent Component</h1>
      <MemoChild data={`Count: ${count}`} />
      {memoizedExpensiveChild}
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <button onClick={() => setData('New Data')}>Update Data</button>
    </div>
  );
}

export default Parent;

2. 组件功能解析

MemoChild

  • 使用 React.memo 包裹,只有当其 data 属性变化时才会重新渲染。

ExpensiveChild

  • 普通的子组件,父组件使用 useMemo 来缓存其实例。
  • 只有当 data 属性变化时,useMemo 会重新计算并返回新的组件实例。

Parent

  • 管理两个状态:countdata
  • 点击"Increment Count"按钮时,只有 MemoChild 会更新,而 ExpensiveChild 的引用保持不变。
  • 点击"Update Data"按钮时,ExpensiveChild 会重新渲染,因为 data 发生了变化。

3. 运行结果

点击"Increment Count"按钮

  • count 状态更新,MemoChild 会重新渲染,控制台输出:

    复制代码
    MemoChild rendered
  • ExpensiveChild 不会重新渲染,控制台不会输出。

点击"Update Data"按钮

  • data 状态更新,ExpensiveChild 会重新渲染,控制台输出:

    复制代码
    Calculating ExpensiveChild
    ExpensiveChild rendered

4. useMemoReact.memo 对比:

useMemo

  • Hook钩子函数,用于缓存计算结果。只有当依赖项变化时,才会重新计算。
  • 使用useMemo 缓存 ExpensiveChild 实例,避免不必要的重新渲染。

React.memo

  • 高阶组件,缓存组件的渲染结果。只有当传入的 props 发生变化时,组件才会重新渲染。
  • 适用于根据 props 变化控制渲染的场景。

5. 渲染逻辑总结

基本数据类型(如 numberstringboolean

  • 当组件的 props 是基本数据类型时,如果其值未发生变化,React.memo 不会重新渲染组件。

引用数据类型(如 objectarray

  • 当组件的 props 是引用数据类型时,React.memo 会进行浅比较。
  • 如果引用相同,组件不会重新渲染;如果引用不同,组件会重新渲染。

6. 关键点

  • 基本数据类型的比较:只要值相同,组件不会重新渲染。
  • 引用数据类型的比较:如果引用相同,组件不会重新渲染;如果引用不同(无论内容是否相同),组件会重新渲染。
相关推荐
tiana_3 分钟前
写了个零依赖的 Go 版本管理器,curl | bash 完事
开发语言·golang·bash
嘘嘘出差12 分钟前
Python 爬虫入门实战:爬取豆瓣电影 Top 250
开发语言·爬虫·python
爱写代码的倒霉蛋17 分钟前
实现协程的三种方式
开发语言·python
多加点辣也没关系1 小时前
JavaScript|第12章:属性配置与 getter/setter
javascript
CS创新实验室1 小时前
NumPy数组的C风格和Fortran风格
c语言·开发语言·numpy
gis开发之家1 小时前
《Vue3 从入门到大神29篇》单元测试与 E2E 测试 —— 保障 Vue3 项目的质量
前端·javascript·vue.js·单元测试·前端框架·vue3
逝水无殇2 小时前
C# 正则表达式详解
开发语言·后端·正则表达式·c#
朱永博2 小时前
使用Onnruntime实现Padim/Patchcore推理
开发语言·c#
前端H2 小时前
Biome & Rolldown:Rust 工具链接管前端基建
开发语言·前端·rust
柒和远方2 小时前
从等待到流式:LLM 流式输出的原理、协议与工程实践
javascript·llm