揭秘 React Hooks:useCallback 和 useMemo
React Hooks 引入了使用函数式组件(而非类)的同时使用状态和其他生命周期特性的功能。Hooks 是一种更简单的方法,可以在用户界面中封装状态行为和副作用,同时减少代码量并提高可读性。
有些钩子比其他钩子更容易理解和使用,因此本系列文章将重点揭秘那些不那么简单的钩子。我们首先解释组件重新渲染时会发生什么,然后定义 useCallback 和 useMemo 的用途,最后讨论何时适合使用这些钩子,何时不适合。
当组件重新渲染时会发生什么?
你可能已经知道,React 会在每次 state 或 props 改变时重新渲染组件。由于 JavaScript 中函数被视为对象,因此在 React 函数式组件下创建的所有对象(包括函数)在每次重新渲染时都会重新创建。这是引用相等性的结果,这意味着两个看起来完全相同的对象并不相同,除非它们指向同一个对象。
换句话说,当 React 组件即将重新渲染时,它会将原始组件下创建的每个对象与新版本进行比较。即使这些对象完全相同,它们指向的对象也并非同一个,因此 React 会将它们识别为不同的对象,并允许在每次重新渲染时重新创建它们。
useCallback 和 useMemo 的用途是什么?
如果正确使用useCallback和useMemo ,其目的是防止不必要的重新渲染并提高代码的效率。
我们来看看它们的结构。这两个钩子都接收两个参数:
1)一个函数
2)一个依赖项数组
useCallback钩子返回传递的函数的相同实例(参数#1),而不是每次组件重新渲染时都创建一个新的实例。
仅当依赖项数组(参数 #2)发生变化时,它才会创建所传递函数的新实例(参数 #1)。
让我们看一个例子。这里有一个简单的应用程序,用于对两个值进行加法运算。用户可以增加第一个值和/或减少第二个值,结果也会相应更新。我们还有一个extra
用户可以更新的第三个值,但是这个值在计算中没有用到。
如果用户与extra
状态值交互,即使 extraVal 未在其中使用,组件也会重新渲染并创建 additionResult 函数的新副本。在此示例中,我们实现了useCallback钩子,以便仅在 firstVal 或 secondVal 更新时才创建 additionResult 函数的新副本。
useMemo hook 非常类似,但是,它不像 useCallback 那样返回一个未调用的函数,而是调用传入的函数,并且仅在参数数组发生变化时返回结果值。换句话说,useMemo仅在必要时调用传入的函数,并在所有其他渲染时返回缓存值。
在这个例子中,我们实现了一个应用程序,它接受一个数字并返回其阶乘。例如,如果我们输入数字 5,它会使用递归函数来计算 5!= 5*4*3*2*1=120。在本例中,我们使用 useMemo hook 来告诉 React 仅在数字发生变化时重新计算。
何时使用它们?
如果您考虑在组件的任何地方添加useCallback和useMemo钩子,请不要这样做。
这两个钩子都会给你的代码增加一些额外的复杂性,并且它们需要在后台进行很多工作。
使用 useCallback 和 useMemo 添加性能优化的成本很高,并且这些优化并不总是能带来足够的好处来抵消其成本。
您应该考虑在以下情况下使用useCallback和/或useMemo钩子:
1)处理大量数据
2)使用交互式图形和图表
3)实现动画
4)合并组件延迟加载(特别是 useMemo)
概括
当组件重新渲染时,它会创建所有对象的新实例,包括其中的所有功能。
useCallback - 允许您在渲染之间缓存函数的实例。
useMemo - 允许您在渲染之间缓存一个值。
我希望这篇文章对您有所帮助,并且您将在下一个项目中自信地开始使用useCallback和useMemo 。
我每周都会发布新内容。下周日我们将探索一个不同的 React Hook!
文章来源:https://dev.to/milu_franz/demystifying-react-hooks-usecallback-and-usememo-1a8j