如何测量 React.memo 的渲染?

问题描述 投票:0回答:1

我有一个使用备忘录的简单反应组件,例如:

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

我如何衡量这份备忘录的成功程度?例如:我想知道它由于备忘录而跳过重新渲染的频率。是否有一个通用的钩子/实用程序可以用来测量这个?

我想知道所有尝试渲染的计数以及由于备忘录而跳过的渲染的计数。

也许有我自己的备忘录功能来计算这个?正在想这样的事情:

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;
  });
}

不知道如何调用默认的备忘录比较,或者有更好的方法吗?

reactjs react-memo
1个回答
0
投票

我如何衡量这份备忘录的成功程度?例如:我想知道如何 通常它会因为备忘录而跳过重新渲染。有通用的吗 我可以用来测量这个的目的钩子/实用程序?

不,没有任何“开箱即用”的东西可以衡量这一点。

一般来说,证明否定性也相当困难。证明组件在您期望时呈现比证明它在您不期望时未呈现更容易。

我想知道所有尝试渲染的计数和计数 由于备忘录而被跳过的渲染。

如果您只是想知道

memo
高阶组件在父子耦合之间的效果如何,您可以使用 React ref 来跟踪组件的渲染计数,并比较计数。

示例:

const renderCountRef = React.useRef(0);

React.useLayoutEffect(() => {
  renderCountRef.current++;
});

演示

这是一个父组件具有两种状态的演示,

count1
count2
,其中
count1
作为道具传递给子组件,并触发子组件重新渲染。您可以在这里观察到,子组件仅在其自身状态更新或从父组件传递的 prop 值发生更改时重新渲染。当父组件的
count2
状态更新并且父组件重新渲染时,观察子组件没有重新渲染。

const Child = (props) => {
  const [count, setCount] = React.useState(0);
  const renderCountRef = React.useRef(0);

  React.useLayoutEffect(() => {
    renderCountRef.current++;
  });

  return (
    <React.Fragment>
      <h2>Child</h2>
      <div>
        State: {count}{" "}
        <button type="button" onClick={() => setCount((c) => c + 1)}>
          +1
        </button>{" "}
        --- Renders: {renderCountRef.current}
      </div>
      <div>Parent State1: {props.state1}</div>
    </React.Fragment>
  );
};

const MemoizedChild = React.memo(Child);

const Parent = () => {
  const [count1, setCount1] = React.useState(0);
  const [count2, setCount2] = React.useState(0);
  const renderCountRef = React.useRef(0);

  React.useLayoutEffect(() => {
    renderCountRef.current++;
  });

  return (
    <div className="App">
      <h2>Parent</h2>
      <div>
        State1: {count1}{" "}
        <button type="button" onClick={() => setCount1((c) => c + 1)}>
          +1
        </button>{" "}
        --- State2: {count2}{" "}
        <button type="button" onClick={() => setCount2((c) => c + 1)}>
          +1
        </button>{" "}
        --- Renders: {renderCountRef.current}
      </div>

      <hr />
      <MemoizedChild state1={count1} />
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);

root.render(
  <React.StrictMode>
    <Parent />
  </React.StrictMode>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<div id="root" />

© www.soinside.com 2019 - 2024. All rights reserved.