介绍
随着 React 16.8 的发布,您现在可以在 React 应用程序中使用许多有用的钩子。在 16.8 中引入的内置钩子之一是useMemo
。
本文将探讨 React 中的重新渲染如何工作,为什么 React 应用程序会考虑这一点,以及useMemo
链接如何利用它来提高应用程序的性能。
前提条件
要完成本教程,您将需要:
在本教程开始之前对 React 的基本理解. 您可以通过遵循 如何在 React.js 中编码系列来了解更多关于 React 的信息。
参考平等和昂贵的操作
有两个问题useMemo
试图解决:
- 参考等式
- 计算成本昂贵的操作
在组件的生命周期中,React在进行更新时重新渲染组件。当React检查组件的任何更改时,它可能会检测到由于JavaScript如何处理平等和浅色比较而发生的意外或意想不到的变化。
此外,如果重新渲染是一项昂贵的操作,例如长时间的循环
,它可能会损害性能,昂贵的操作可能耗费时间,内存或处理,除了潜在的技术问题,这可能导致用户体验不佳。
如果一个部分重新渲染,它会重新渲染整个组件树。
因此,React发布了备忘录
的想法来修复这一点。
记忆的理解
Memoization 是一种优化技术,它通过一个复杂的函数来被记忆化,在记忆化中,当相同的参数随后被传入时,结果被记忆
。
如果我们有一个函数计算1 + 1
,它会返回2
,但如果它使用备忘录,下一次我们通过函数运行1
,它不会添加它们;它只会记住答案是2
,而不会执行添加函数。
从官方的 React 文档中,‘useMemo’的签名看起来是这样的:
1const memoizedValue = React.useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo
包含一个函数和一系列依赖。
依赖行为类似于函数中的参数。依赖的列表是元素useMemo
时钟:如果没有变化,函数的结果将保持相同。否则,它将重新运行函数。如果它们不改变,如果我们的整个组件重新渲染,它不会重新运行,而是返回存储的结果。
创建一个useMemo
示例
以下是使用useMemo
用于使用两个计算成本昂贵函数的项目组的一个抽象示例:
1const List = React.useMemo(() =>
2 listOfItems.map(item => ({
3 ...item,
4 itemProp1: expensiveFunction(props.first),
5 itemProp2: anotherPriceyFunction(props.second)
6 })), [listOfItems]
7)
在上面的例子中,useMemo
函数会在第一个渲染中运行,它会阻止线程,直到昂贵的函数完成,因为useMemo
在第一个渲染中运行。
起初,这不会像useEffect
那样干净,因为useEffect
可以使加载旋转,直到昂贵的功能结束,效果熄灭。
然而,在随后的渲染中,只要listOfItems
从未改变,这些昂贵的函数就不再需要重新运行,而useMemo
将记住
每个函数的返回值。
它会使这些昂贵的功能看起来是即时的,如果你有一个昂贵的同步功能或两个,这是理想的。
何时使用useMemo
首先写下代码,然后重新查看它,看看是否可以优化它. 如果你在应用程序中执行useMemo
太频繁,它可能会损害性能。
当寻求实现useMemo
时,您可以使用配置文件工具来识别昂贵的性能问题。 Expensive 意味着它使用了大量的资源(如内存)。
为工作使用正确的钩子
除了useMemo
,还有useCallback
,useRef
和useEffect
。
useCallback
链接类似于useMemo
,但返回了一个备忘录的函数,而useMemo
有一个返回值的函数。
如果你的依赖数组不提供,则没有记忆的可能性,它会在每个渲染上计算一个新的值。在这种情况下,你可以使用useRef
链接。
您不希望useMemo
消除任何副作用或任何非同步呼叫,在这些情况下,您应该使用useEffect
。
结论
本文探讨了useMemo
链接以及何时在React应用程序中使用它是合适的。
useMemo
可以通过记住
昂贵的功能来帮助应用程序的性能,并防止每次应用程序发生更改时重新渲染。
虽然可以通过使用此链接来提高性能,但如果您过度使用该链接,它也可以减慢您的应用程序,您使用的链接越多,您的应用程序必须分配更多的内存。
若要了解更多关于 React 的最佳实践,请遵循 DigitalOcean 上的完整 如何在 React.js 中编码系列。