面试官:说一下你对 useMemo 和 React.memo 的理解

前言

React 中的这两个函数都带有 memo,看着比较相似,但是作用和使用场景却不一致。

memo 的英文含义为备忘录,可以理解为保存,记忆之类,从字面意思可以猜测到它的作用。

可能没有实战的童鞋还容易把这两个搞混,但是这两个函数有着完全不一样的功能,也不需要拿来比较,千万不要搞混了,今天就带大家一起来详细的分析一下这两个函数的作用和使用场景!

useMemo

useMemo 是 React 中用来进行性能优化的钩子函数之一,它的作用是用来缓存计算结果,只有在依赖项发生变化时才重新计算,可以有效减少不必要的计算开销。常见的使用场景是在需要进行大量计算或者复杂逻辑的组件中,通过 useMemo 缓存计算结果,避免不必要的重复计算,可以提高组件的性能。

当点击按钮时,count 会加1,而使用 useMemo 则会监听到依赖项的变化,此时会计算得到doubledCount,熟悉 Vue 的小伙伴应该会知道,和 computed 相似。

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

const App = () => {
  const [count, setCount] = useState(0);

  // 通过 useMemo 缓存计算结果
  const doubledCount = useMemo(() => {
    return count * 2;
  }, [count]);


  return (
    <div>
      <h1>useMemo Example</h1>
      <p>Count: {count}</p>
      <p>Doubled Count: {doubledCount}</p>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
    </div>
  );
};

export default App;

React.memo

使用 React的小伙伴都了解,当组件中的 state 数据发生变化时,会重新渲染该组件,如果引入子组件,子组件也会重新渲染,这会造成不必要的开销。React.memo 则是用来解决这个问题的。

作用

React.memo 会浅比较当前组件的 props 与上一次渲染时的 props。如果 props 没有变化,则跳过渲染过程。

在这个案例中,我们有两个点击事件,其中点击 handleChangeCount 会引起 count 的改变,当 count 改变时,会引起组件重新渲染,在组件中引入了子组件 MyComponent ,默认情况下 MyComponent 也会重新渲染。

很明显我们可以发现,MyComponent 里面并没有用到 count,也就是说 MyComponent 组件并不需要重新渲染,MyComponent 只需要在自己依赖的 props 改变时重新渲染,所以我们使用 React.memo 进行包裹,包裹之后只会在 props 发生变化时重新渲染 MyComponent 组件 。

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

// 一个纯函数组件
const MyComponent = React.memo(({ name, age }) => {
  console.log('MyComponent rendered');
  return (
    <div>
      <h2>{name}</h2>
      <p>Age: {age}</p>
    </div>
  );
});

const App = () => {
  const [person, setPerson] = useState({ name: 'John', age: 30 });
  const [count, setCount] = useState(0);

  const handleChangeAge = () => {
    setPerson({ ...person, age: person.age + 1 });
  };

  const handleChangeCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <MyComponent name={person.name} age={person.age} />
      <button onClick={handleChangeAge}>Change Age</button>
      <button onClick={handleChangeCount}>Change Count</button>
      <p>Count: {count}</p>
    </div>
  );
};

export default App;

通过使用 React.memo,我们避免了 MyComponent 在不必要的情况下重新渲染,从而提高了性能。

需要注意的是,React.memo 只会对函数组件进行浅层比较。如果 props 是一个引用类型(如对象或数组),即使属性值没有改变,React 也会认为它是一个新的引用,从而导致组件重新渲染。在这种情况下,可以使用 React.memo 的第二个参数来提供一个自定义的比较函数。

通过自定义第二个参数,拿到前一个跟后一个 props,从而比较里面的属性值是否发生变化而决定是否重新渲染组件。

js 复制代码
import React from 'react';

const Person = React.memo(({ person }) => {
  console.log('Person component rendered');
  return (
    <div>
      <h2>{person.name}</h2>
      <p>Age: {person.age}</p>
    </div>
  );
}, (prevProps, nextProps) => {
  // 自定义比较函数
  const prevPerson = prevProps.person;
  const nextPerson = nextProps.person;

  // 比较 person 对象的属性值
  return (
    prevPerson.name === nextPerson.name &&
    prevPerson.age === nextPerson.age
  );
});

const App = () => {
  const [person, setPerson] = React.useState({ name: 'John', age: 30 });

  const handleChangeAge = () => {
    setPerson({ ...person, age: person.age + 1 });
  };

  return (
    <div>
      <Person person={person} />
      <button onClick={handleChangeAge}>Change Age</button>
    </div>
  );
};

export default App;
相关推荐
超哥--5 小时前
B站视频内容智能分析系统(九):React 前端与管理面板
前端·react.js·前端框架
Cutecat_8 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
dsyyyyy11018 小时前
JavaScript变量
开发语言·javascript·ecmascript
qq_422152578 小时前
PDF 加水印工具怎么选?2026 年文档版权保护方案对比
前端·pdf·github
kyriewen8 小时前
手写 Promise.all、race、any:不到 30 行代码,解决并发异步的所有姿势
前端·javascript·面试
brucelee1869 小时前
OpenClaw 浏览器控制(Chrome MCP)完整教程
前端·chrome
ct9789 小时前
React 状态管理方案深度对比
开发语言·前端·react
胡志辉的博客10 小时前
深入浅出理解浏览器事件循环:从一道输出题讲到 Chrome 源码
前端·javascript·chrome·chromium·event loop
代码不加糖10 小时前
js中不会冒泡的事件有哪些?
前端·javascript·vue.js
懂懂tty10 小时前
Vue2与Vue3之间API差异
前端·javascript·vue.js