React 优化神器:useMemo 和 memo

161 阅读2分钟

React 中,useMemomemo 都用于 优化性能,减少不必要的渲染,但它们的使用场景不同。

1. useMemo(记忆化计算)

📌 作用

  • 缓存计算结果,避免每次渲染都重新计算
  • 只有当 依赖项 发生变化时,才会重新计算

✅ 适用场景

  • 计算量较大的值(避免重复计算)
  • 避免子组件不必要的渲染(与 useCallback 结合使用)

💡 代码示例

import React, { useState, useMemo } from "react";

const ExpensiveCalculation = ({ num }: { num: number }) => {
  const result = useMemo(() => {
    console.log("计算中...");
    return num * 2; // 假设这是一个昂贵的计算
  }, [num]);

  return <p>计算结果: {result}</p>;
};

export default function App() {
  const [count, setCount] = useState(0);
  const [num, setNum] = useState(5);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>增加 count</button>
      <button onClick={() => setNum(num + 1)}>增加 num</button>
      <p>count: {count}</p>
      <ExpensiveCalculation num={num} />
    </div>
  );
}
  • useMemo 缓存计算结果,当 num 变化时才重新计算
  • 点击 count 按钮时num 没变,因此不会重新计算

2. memo(组件缓存)

📌 作用

  • 缓存组件,如果 props 没变,则不会重新渲染

✅ 适用场景

  • 组件 性能优化,防止不必要的渲染
  • 适用于 功能组件(Functional Component)

💡 代码示例

import React, { useState, memo } from "react";

const Child = memo(({ name }: { name: string }) => {
  console.log("子组件渲染...");
  return <p>子组件: {name}</p>;
});

export default function App() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState("React");

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>增加 count</button>
      <button onClick={() => setName("React " + Math.random())}>改变 name</button>
      <p>count: {count}</p>
      <Child name={name} />
    </div>
  );
}
  • Child 组件使用 memo 进行缓存
  • 点击 count 按钮时name 没变,所以 Child 不会重新渲染
  • 点击 name 按钮时Child 才会重新渲染

3. useMemo vs memo 的区别

useMemo

作用: 记忆化 计算值

优化点: 避免重复计算

依赖项: useMemo(fn, [deps])

适用场景: 计算量大的数据处理

返回值: 计算结果

memo

作用: 记忆化 组件

优化点: 避免组件不必要的渲染

依赖项: 组件的 props

适用场景: 组件的性能优化

返回值: 缓存组件

4. useMemomemo 结合使用

可以 同时使用 useMemomemo 来优化 React 组件。

💡 示例

import React, { useState, useMemo, memo } from "react";

const Child = memo(({ num }: { num: number }) => {
  const result = useMemo(() => {
    console.log("计算 num * 2...");
    return num * 2;
  }, [num]);

  console.log("子组件渲染...");

  return <p>计算结果: {result}</p>;
});

export default function App() {
  const [count, setCount] = useState(0);
  const [num, setNum] = useState(5);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>增加 count</button>
      <button onClick={() => setNum(num + 1)}>增加 num</button>
      <p>count: {count}</p>
      <Child num={num} />
    </div>
  );
}
  • memo 防止 Child 组件无意义渲染
  • useMemo 缓存 num * 2 的计算值
  • 点击 count 按钮时Child 不会重新渲染
  • 点击 num 按钮时Child 重新渲染并重新计算

总结

  • useMemo 适用于避免重复计算
  • memo 适用于避免子组件不必要的渲染
  • 两者可以结合使用来优化 React 性能