面试官:说一下你对 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;
相关推荐
随云6324 分钟前
WebGL编程指南之着色器语言GLSL ES(入门GLSL ES这篇就够了)
前端·webgl
无知的小菜鸡7 分钟前
路由:ReactRouter
react.js
寻找09之夏1 小时前
【Vue3实战】:用导航守卫拦截未保存的编辑,提升用户体验
前端·vue.js
非著名架构师1 小时前
js混淆的方式方法
开发语言·javascript·ecmascript
多多米10052 小时前
初学Vue(2)
前端·javascript·vue.js
敏编程2 小时前
网页前端开发之Javascript入门篇(5/9):函数
开发语言·javascript
柏箱2 小时前
PHP基本语法总结
开发语言·前端·html·php
新缸中之脑2 小时前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法
hmz8562 小时前
最新网课搜题答案查询小程序源码/题库多接口微信小程序源码+自带流量主
前端·微信小程序·小程序
看到请催我学习2 小时前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript