React.memo(明智地使用我)

2025-06-08

React.memo(明智地使用我)

React.memo是一个相当简单但被误解的高阶组件。通过文档我们得到这样的定义:

如果你的函数组件在给定相同 props 的情况下渲染相同的结果,你可以将其包装在对 React.memo 的调用中,以便在某些情况下通过记忆结果来提升性能。这意味着 React 将跳过渲染组件,并重用上次渲染的结果。

性能提升🤩?哇,那就让我们把一切都记录下来吧!

⚠️ 冷静下来,夏洛克,明智地使用它。

首先,让我们深入了解一下内部发生了什么神奇的事情。memo当我说它很简单时,在查看了React repo 中的代码后,你一定会同意我的说法。整个代码基本上是这样的:

const REACT_MEMO_TYPE = Symbol.for('react.memo');

export function memo<Props>(
  type,
  compare?: (oldProps: Props, newProps: Props) => boolean
) {
  const elementType = {
    $$typeof: REACT_MEMO_TYPE,
    type,
    compare: compare === undefined ? null : compare,
  };

  return elementType;
}

所以这意味着当你使用它SomeComponent并传递它时你基本上会得到回报:

  {
    $$typeof: Symbol.for('react.memo'),
    type: SomeComponent,
    compare: compare || null,
  }

这意味着,如果你直接使用它,你会得到同样的结果,不相信吗?在codesandbox中试试吧。

你会注意到, for 有第二个参数memo,它是一个compare函数。让我们再看一下文档:

默认情况下,它只会对 props 对象中的复杂对象进行浅层比较。如果你想控制比较过程,也可以提供自定义比较函数作为第二个参数。

这意味着,即使 props 发生变化,我们也可以决定组件是否应该重新渲染。假设你不希望组件在第一次渲染后再次重新渲染(无论出于什么原因),你可以简单地这样做:

const MemoComponent = React.memo(({ name }) => {
  return <div>{name}</div>;
}, () => true);

⚠️ 注意,我在比较函数中返回的是true,我基本上是在说,之前有意义的 props 与下一个 props 相同,所以它不应该重新渲染。(它基本上是 的逆shouldComponentUpdate

那么什么时候该正确使用它呢?主要当你的组件是纯函数式组件,并且/或者它总是使用相同的 props 进行渲染,并且你想控制它是否应该渲染时,你应该使用它。例如,假设你有以下组件:

const UserInfoHeader = ({avatar, name}) => (
    <>
        <img src={avatar} />
        <div>Hi {name}</div>
    </>
)

您可能会在某些仪表板中使用它,这是一个绝佳的使用机会memo,您的仪表板可能会重新渲染并更改几个内部状态,但不太可能更改名称或头像源,因此UserInfoHeader使用 React.memo 包装将避免此处不必要的渲染。

现在我们对它有了更好的理解,但是如果我们用 包裹所有内容,会有什么问题呢memo?什么时候应该避免这种情况?

不明智地使用memo会导致难以调试的错误,并给人一种提高性能的错觉。那么问题是什么时候不该使用React.memo

1. 道具经常更换

React.memo每次渲染时比较 props 是有成本的,如果你的组件一直在更新 props,你可能会损失性能,因为普通组件不会关心它,只会正常重新渲染。

2. 比较函数开销太大

假设你有一个复杂的对象作为 prop 传递,并且你想进行一次非常昂贵的计算来比较前一个对象和新对象。注意,与简单的始终重新渲染相比,这样做可能会降低性能。

3. 接收函数作为 props 的组件

这不是什么禁忌,但在记忆组件中使用回调时要小心,例如:

const Input = React.memo(...)

const App = () => (<Input onChange={(e) => { console.log(e) }} />)

在这种情况下,Input无论如何都会重新渲染,因为在每次App渲染中我们都会重新定义,onChange所以Input要么在这里使用静态函数,要么将其与结合起来useCallback以防止它发生。


总结

React.memo它是一个功能强大且易于使用的 HOC,可以提升性能,但误用可能会适得其反,甚至损害性能。请务必谨慎使用,并使用一些性能分析工具来确保其用例有效。

你有什么好的使用示例吗?memo或者你遇到过相关的 bug 吗?请在评论区分享。:)

鏂囩珷鏉ユ簮锛�https://dev.to/assuncaocharles/react-memo-use-me-wisely-m5l
PREV
如何使用 Nuxt.js 构建 Jamstack 多语言博客
NEXT
构建并发布您的第一个 NPM 包