gpt4 book ai didi

javascript - 如果 areEqualFunction 执行复杂/大量比较,使用 React.memo 是否更快?

转载 作者:行者123 更新时间:2023-12-04 17:16:11 25 4
gpt4 key购买 nike

假设我有以下代码:

import React, { memo } from 'react';

const MyComponent = ({ arrayOfStuff }) => (
<div>
{arrayOfStuff.map(element => (
<p key={element.foo}>element.foo</p>
))}
</div>
);

const areEqual = (prevProps, nextProps) => {
const prevArrayOfStuff = prevProps.arrayOfStuff;
const nextArrayOfStuff = nextProps.arrayOfStuff;
if (prevArrayOfStuff.length !== nextArrayOfStuff.length)
return false;

for (let i; i < prevArrayOfStuff.length && i < nextArrayOfStuff.length; ++i) {
if (prevArrayOfStuff[i].foo !== nextArrayOfStuff[i].foo)
return false;
}

return true;
};

export default memo(MyComponent, areEqual);

假设 arrayOfStuff 非常大,可能有数百个元素。我真的节省了很多内存组件的时间吗?我认为如果 props 相同,它会迭代所有元素而不考虑备忘录,因为 areEqual 和渲染函数都是这样做的。

最佳答案

对此的最佳答案是:剖析它并查看。 :-)

但是,尽管您的数组中可能有数百个条目,但您所做的检查并不复杂,而且非常简单快捷。 (我会在开头添加一个 if (prevArrayOfStuff === nextArrayOfStuff) { return true; }。)

一些优点和缺点:

优点:

  • 您的检查非常简单快速,即使是数百个元素也是如此。

  • 如果没有发现任何变化,则保存:

    • 创建一堆对象(组件返回的 React“元素”)。
    • React 必须将先前元素的键与新元素的键进行比较,以查看是否需要更新 DOM。
  • 请记住,只要其父级发生任何更改,您的组件就会被调用以重新呈现,即使这些更改与您的组件无关。

缺点:

  • 如果 数组中经常发生变化,那么您只是在没有任何返回的情况下添加更多工作,因为 areEqual 将返回 false 无论如何。

  • areEqual 需要持续的维护成本,并且存在错误的机会。

因此,这实际上归结为您的整个应用发生了哪些变化,尤其是组件的父级。如果那些 parent 的状态或 Prop 经常变化但与您的组件无关,那么您的组件进行检查可以节省大量时间。

这里展示了当 parent 中的某些内容发生更改时,即使其 props 中没有任何内容发生更改,您的组件将如何被调用以重新渲染:

没有内存它(如果没有任何变化,React 实际上不会更新 DOM 元素,但是你的函数被调用并创建 React 元素,React 将其与渲染的元素进行比较):

const {useState, useEffect} = React;

// A stand-in for your component
const Example = ({items}) => {
console.log("Example rendering");
return <div>
{items.map(item => <span key={item}>{item}</span>)}
</div>;
};

// Some other component
const Other = ({counter}) => {
console.log("Other rendering");
return <div>{counter}</div>;
};

// A parent component
const App = () => {
// This changes every tick of our interval timer
const [counter, setCounter] = useState(0);
// This changes only every three ticks
const [items, setItems] = useState([1, 2, 3]);

useEffect(() => {
const timer = setInterval(() => {
setCounter(c => {
c = c + 1;
if (c % 3 === 0) {
// Third tick, change `items`
setItems(items => [...items, items.length + 1]);
}
// Stop after 6 ticks
if (c === 6) {
setTimeout(() => {
console.log("Done");
}, 0);
clearInterval(timer);
}
return c;
});
}, 500);
return () => clearInterval(timer);
}, []);

return <div>
<Example items={items} />
<Other counter={counter} />
</div>;
};

ReactDOM.render(<App/>, document.getElementById("root"));
.as-console-wrapper {
max-height: 80% !important;
}
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

记住它:

const {useState, useEffect} = React;

// A stand-in for your component
const Example = ({items}) => {
console.log("Example rendering");
return <div>
{items.map(item => <span key={item}>{item}</span>)}
</div>;
};

const examplePropsAreEqual = ({items: prevItems}, {items: nextItems}) => {
const areEqual = (
prevItems === nextItems ||
(
prevItems.length === nextItems.length &&
prevItems.every((item, index) => item === nextItems[index])
)
);
if (areEqual) {
console.log("(skipped Example)");
}
return areEqual;
}

const ExampleMemoized = React.memo(Example, examplePropsAreEqual);

// Some other component
const Other = ({counter}) => {
console.log("Other rendering");
return <div>{counter}</div>;
};

// A parent component
const App = () => {
// This changes every tick of our interval timer
const [counter, setCounter] = useState(0);
// This changes only every three ticks
const [items, setItems] = useState([1, 2, 3]);

useEffect(() => {
const timer = setInterval(() => {
setCounter(c => {
c = c + 1;
if (c % 3 === 0) {
// Third tick, change `items`
setItems(items => [...items, items.length + 1]);
}
// Stop after 6 ticks
if (c === 6) {
setTimeout(() => {
console.log("Done");
}, 0);
clearInterval(timer);
}
return c;
});
}, 500);
return () => clearInterval(timer);
}, []);

return <div>
<ExampleMemoized items={items} />
<Other counter={counter} />
</div>;
};

ReactDOM.render(<App/>, document.getElementById("root"));
.as-console-wrapper {
max-height: 80% !important;
}
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

关于javascript - 如果 areEqualFunction 执行复杂/大量比较,使用 React.memo 是否更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68664553/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com