You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统计React.memo的渲染次数与跳过渲染次数?

如何衡量React memo的渲染优化效果?

我有一个使用memo的简单React组件,示例如下:

const Greeting = memo(function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
});

我该如何衡量这个memo的效果?比如,我想知道它因memo跳过重新渲染的频率。有没有通用的Hook或工具可以用来统计?我希望了解所有尝试渲染的次数,以及因memo而跳过的渲染次数。

或许可以自己编写一个memo函数来统计?我想到了如下实现方式:

function memoProfile(Component, arePropsEqual) {
  let allRenders = 0;
  let skippedRenders = 0;

  return memo(Component, (prevProps, nextProps) => {
    allRenders++;

    const propsEqual = arePropsEqual
      ? arePropsEqual(prevProps, nextProps)
      : false; // TODO: use default memo comparison

    if (propsEqual) {
      skippedRenders++;
    }

    console.log(`Skipped renders: ${skippedRenders}/${allRenders} (${(skippedRenders / allRenders * 100).toFixed(2)}%)`);

    return propsEqual;
  });
}

我不确定如何调用默认的memo比较函数,或者有没有更好的方法?


一、用React DevTools直接统计(最便捷)

React DevTools的Profiler面板是官方原生工具,能直接统计组件的渲染与跳过情况:

  • 打开DevTools切换到Profiler标签,点击录制按钮
  • 操作应用触发组件更新,录制结束后查看目标组件的「Render Count」(总渲染尝试次数)和「Skipped renders」(因memo跳过的次数)
  • 还能查看每次渲染的触发原因,精准判断是否是props变化导致的渲染

二、完善自定义带统计的memo封装

你写的memoProfile思路可行,核心问题是React没暴露默认的props比较函数,但我们可以模拟其浅比较逻辑(React默认就是用浅比较判断props是否相等):

// 实现React默认的浅比较逻辑
function shallowEqual(prevProps, nextProps) {
  if (prevProps === nextProps) return true;
  const prevKeys = Object.keys(prevProps);
  const nextKeys = Object.keys(nextProps);
  if (prevKeys.length !== nextKeys.length) return false;
  for (const key of prevKeys) {
    if (!nextProps.hasOwnProperty(key) || prevProps[key] !== nextProps[key]) {
      return false;
    }
  }
  return true;
}

function memoProfile(Component, arePropsEqual = shallowEqual) {
  let allRenders = 0;
  let skippedRenders = 0;

  const ProfiledComponent = memo(Component, (prevProps, nextProps) => {
    allRenders++;
    const propsEqual = arePropsEqual(prevProps, nextProps);
    if (propsEqual) {
      skippedRenders++;
    }
    console.log(`[${Component.displayName || Component.name}] Skipped: ${skippedRenders}/${allRenders} (${(skippedRenders / allRenders * 100).toFixed(2)}%)`);
    return propsEqual;
  });

  // 给组件加标识,方便在DevTools中识别
  ProfiledComponent.displayName = `MemoProfile(${Component.displayName || Component.name || 'Component'})`;
  return ProfiledComponent;
}

使用方式:

const Greeting = memoProfile(function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
});

三、用自定义Hook统计实际渲染次数

如果不想封装memo,也可以写Hook统计组件的实际渲染次数,再结合父组件的更新次数对比得出跳过次数:

function useRenderCount(label = 'Component') {
  const renderCount = useRef(0);
  useEffect(() => {
    renderCount.current++;
    console.log(`[${label}] 实际渲染次数: ${renderCount.current}`);
  });
  return renderCount.current;
}

在组件中使用:

const Greeting = memo(function Greeting({ name }) {
  useRenderCount('Greeting');
  return <h1>Hello, {name}!</h1>;
});

内容的提问来源于stack exchange,提问作者Vic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 09:35:08