随着 React 16.8 的发布,您现在可以在 React 应用程序中使用许多有用的钩子。 16.8 中引入的内置 Hooks 之一是useMemo
。该挂钩有可能提高应用程序的性能。
本文将探讨重新渲染在 React 中的工作原理、为什么这是 React 应用程序的一个重要考虑因素,以及如何重新渲染useMemo
hook 可以利用它来提高应用程序的性能。您还将学到什么时候useMemo
可能会导致性能问题。
要完成本教程,您将需要:
- 在开始本教程之前对 React 有基本的了解。您可以通过以下方式了解有关 React 的更多信息如何在 React.js 中编码 series.
有两个问题useMemo
力求解决:
在组件的生命周期中,React 在进行更新时重新渲染组件。当 React 检查组件中的任何更改时,由于 JavaScript 处理相等和浅比较的方式,它可能会检测到意外或意外的更改。 React 应用程序中的此更改将导致其不必要地重新渲染。
此外,如果重新渲染是一项昂贵的操作,例如长时间的for loop
,它会损害性能。昂贵的操作在时间、内存或处理方面可能代价高昂。除了潜在的技术问题之外,这还可能导致糟糕的用户体验。
如果一个部件重新渲染,它会重新渲染整个组件树。
因此,React 发布了memo
解决这个问题的想法。
记忆化是一种传递要记忆的复杂函数的优化技术。在记忆中,当随后传入相同的参数时,结果就会被“记住”。
如果我们有一个计算函数1 + 1
,它将返回2
。但如果它使用记忆化,下次我们运行时1
是通过函数,不会将它们相加;它只会记住答案是2
而不执行添加功能。
来自官方反应文档, useMemo
的签名如下所示:
const memoizedValue = React.useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo
接受一个函数和一组依赖项。
依赖项的作用类似于函数中的参数。依赖项的列表是元素useMemo
手表:如果没有变化,函数结果将保持不变。否则,它将重新运行该函数。如果它们没有改变,即使我们的整个组件重新渲染也没关系,该函数不会重新运行,而是返回存储的结果。如果包装的函数很大且昂贵,这可能是最佳的。这是主要用途useMemo
.
这是一个使用的抽象示例useMemo
对于使用两个计算量大的函数的项目数组:
const List = React.useMemo(() =>
listOfItems.map(item => ({
...item,
itemProp1: expensiveFunction(props.first),
itemProp2: anotherPriceyFunction(props.second)
})), [listOfItems]
)
在上面的例子中,useMemo
函数将在第一次渲染时运行。它会阻塞线程,直到昂贵的函数完成,如useMemo
在第一个渲染中运行。
最初,这看起来不像useEffect
, since useEffect
可以渲染加载旋转器,直到昂贵的函数完成并且效果触发。
然而,在后续渲染中,只要满足以下条件,昂贵的函数就不需要再次运行listOfItems
从未改变。useMemo
会“记住”每个函数的返回值。
这将使这些昂贵的功能看起来是瞬时呈现的。如果您有一两个昂贵的同步函数,那么这是理想的选择。
先写代码,然后再看是否可以优化。如果你实施useMemo
在应用程序中经常出现这种情况可能会损害性能。
当寻求实施时useMemo
,您可以使用分析工具进行检查以识别昂贵的性能问题。昂贵的意味着它正在消耗大量资源(例如内存)。如果您在渲染时在函数中定义了大量变量,则使用 memoize 是有意义的useMemo
.
此外useMemo
,还有useCallback
, useRef
, and useEffect
.
The useCallback
钩子类似于useMemo
,但它返回一个记忆函数,而useMemo
有一个返回值的函数。
如果未提供依赖项数组,则无法记忆,并且它将在每次渲染时计算一个新值。你可以使用useRef
在这种情况下挂钩。优势useMemo
优惠超过useRef
如果依赖关系发生变化,则需要重新记忆。
你不会想拥有useMemo
触发任何副作用或任何异步调用。在这些情况下,您应该使用useEffect
.
本文探讨了useMemo
hook 以及何时适合在 React 应用程序中使用它。
useMemo
可以通过“记住”昂贵的功能并防止每次应用程序发生更改时重新渲染来提高应用程序的性能。
虽然使用此钩子可以提高性能,但如果过度使用它,它也会降低应用程序的速度。使用钩子的次数越多,应用程序分配的内存就越多。
要了解有关 React 最佳实践的更多信息,请遵循完整的如何在 React.js 中编码DigitalOcean 上的系列。