ReactJS

React.memo

React.memo 解决的问题、使用方式和注意事项。

发布于 2026年5月30日0 views

React.memo 用来减少不必要的组件重新渲染。

通俗地说:父组件重新渲染时,子组件默认也会重新渲染。即使子组件收到的 props 没有变化,它也会跟着执行一遍。React.memo 的作用就是:如果 props 没变,就跳过这次子组件渲染。

解决什么问题

假设有一个父组件:

import { useState } from "react";

function UserCard({ name }: { name: string }) {
  console.log("UserCard render");
  return <div>{name}</div>;
}

export function Page() {
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount((value) => value + 1)}>
        {count}
      </button>
      <UserCard name="Alice" />
    </>
  );
}

每次点击按钮,Page 会重新渲染,UserCard 也会重新渲染。可是 UserCardname 一直是 "Alice",其实没必要重新渲染。

这时可以用 memo

import { memo, useState } from "react";

const UserCard = memo(function UserCard({ name }: { name: string }) {
  console.log("UserCard render");
  return <div>{name}</div>;
});

export function Page() {
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount((value) => value + 1)}>
        {count}
      </button>
      <UserCard name="Alice" />
    </>
  );
}

这样 count 改变时,如果 UserCard 的 props 没变,它就可以跳过渲染。

使用方式

基本写法:

import { memo } from "react";

type UserCardProps = {
  name: string;
};

export const UserCard = memo(function UserCard({ name }: UserCardProps) {
  return <div>{name}</div>;
});

也可以这样写:

function UserCard({ name }: UserCardProps) {
  return <div>{name}</div>;
}

export default memo(UserCard);

适合使用的场景

适合:

  • 子组件渲染成本比较高。
  • 子组件 props 大多数时候不变。
  • 父组件经常因为其他状态变化而重新渲染。
  • 列表里的单个复杂项,比如表格行、卡片、图表块。

不太适合:

  • 组件很简单,渲染成本很低。
  • props 每次都会变化。
  • 为了“看起来更优化”到处加 memo

注意事项

React.memo 默认是浅比较 props。

简单值比较没问题:

<UserCard name="Alice" />

但对象、数组、函数每次重新创建时,引用都会变:

<UserCard user={{ name: "Alice" }} />

即使对象内容一样,每次渲染都会创建一个新对象,memo 仍然会认为 props 变了。

可以把对象提到外面,或配合 useMemo

const user = useMemo(() => ({ name: "Alice" }), []);

return <UserCard user={user} />;

函数 props 也一样。如果传给 memo 组件的函数每次都重新创建,memo 效果会变差,这时可以配合 useCallback

和 useCallback 的关系

memo 负责缓存组件渲染结果,useCallback 负责缓存函数引用。

const SaveButton = memo(function SaveButton({
  onSave,
}: {
  onSave: () => void;
}) {
  return <button onClick={onSave}>保存</button>;
});

如果父组件里这样写:

<SaveButton onSave={() => save()} />

每次父组件渲染都会创建一个新函数,SaveButton 仍然会重新渲染。

可以改成:

const handleSave = useCallback(() => {
  save();
}, []);

return <SaveButton onSave={handleSave} />;

总结

React.memo 解决的是“父组件重新渲染导致子组件没必要跟着渲染”的问题。它适合用在较重、props 稳定的组件上;不要盲目到处加,先确认真的存在无意义渲染。