「目标」: 持续输出!每日分享关于web前端常见知识、面试题、性能优化、新技术等方面的内容。
Day8-今日话题
useMemo
是 React 中一个有力的性能优化Hook。可从「用法」、「工作原理」、「作用」、「优缺点」、「使用场景」、「使用注意点」进行学习、复习。
拿vue作比较的话,功能可以类比成vue的计算属性「computed」,都是因为依赖项发生变化而进行重新计算。
1. 用法
useMemo
是 React 中的一个 Hook,用于缓存计算结果,以减少不必要的计算和渲染。它接受两个参数:
-
一个函数,用于计算需要缓存的值。 -
一个依赖数组,包含了在数组中列出的变量发生变化时才重新计算值,可以为空数组或包含多个依赖。
const memoizedValue = useMemo(() => computeExpensiveValue(dep1, dep2), [dep1, dep2]);
2. 工作原理
useMemo
的工作原理涉及到 React 的渲染过程和依赖数组的比较,下面详细介绍其工作原理:
-
「组件的初始渲染和依赖项变化时」:
-
当一个组件首次渲染时或其依赖项发生变化时,React 会执行组件函数内的所有代码,包括 useMemo
。 -
在 useMemo
中,第一个参数是一个计算函数。React 调用这个函数,计算并返回一个值,同时将这个值存储在内部。 -
React 还会将依赖数组( useMemo
的第二个参数)的内容记录下来。
-
「比较依赖项」:
-
当组件重新渲染时,React 会再次执行组件函数,包括 useMemo
。 -
在这个阶段,React会比较当前的依赖数组和上一次渲染时存储的依赖数组。
-
「重新计算或复用」:
-
如果当前的依赖数组和上一次的依赖数组完全相同(即每个元素都严格相等),React 会认为依赖项没有变化,不会重新计算 useMemo
的结果。 -
如果当前的依赖数组和上一次的依赖数组不相等,React 将重新调用 useMemo
中的计算函数,计算并返回新的值。 -
如果依赖数组为空( []
),则useMemo
的结果只会在组件首次渲染时计算一次,并且永远不会重新计算。
-
「返回计算结果」:
-
无论是重新计算还是复用, useMemo
的最终结果都将返回给组件,可以在组件中使用。
这个工作原理确保了 useMemo
只在其依赖项发生变化时才会重新计算,从而有效地避免了不必要的计算和渲染。这对于优化性能和确保组件的一致性非常重要。
需要注意的是,useMemo
返回的是缓存的值,而不是一个函数。如果需要缓存一个函数,可以使用 useCallback
。此外,useMemo
的依赖数组应该包含所有在计算函数中使用的变量,以确保在依赖项变化时重新计算。
3. 作用
-
「性能优化」: useMemo
可以用于缓存昂贵的计算,避免不必要的重新计算,从而提高性能。 -
「避免不必要的渲染」:通过将 useMemo
的结果用作子组件的 prop,可以避免子组件在不必要的情况下重新渲染。 -
「缓存引用类型」:可以缓存引用类型(如对象或数组),以避免在每次渲染时都创建新的引用。
4. 优点
-
「性能优化」:最明显的优点是帮助优化性能,避免不必要的计算和渲染。 -
「可读性」:通过明确指定依赖,代码变得更加可读和可维护。
5. 缺点
-
「滥用可能导致性能问题」:过度使用 useMemo
可能会导致性能问题,因为它可能导致不必要的内存占用。应该谨慎选择使用它,只在需要缓存计算结果时才使用。 -
「复杂性增加」:如果依赖数组包含多个变量,维护这些依赖可能会增加代码复杂性。
6. 使用场景
-
「计算结果昂贵」:用于缓存计算成本高昂的值,例如数学计算、数据筛选、数据转换等。 -
「避免不必要的渲染」:将 useMemo
的结果用作子组件的 prop,以确保子组件只在必要时重新渲染。 -
「缓存引用类型」:当需要在多次渲染之间保持相同的引用类型时,可以使用 useMemo
。
通俗来讲就是说,当前组件或者当前组件所在的父组件修改状态(state)时,我们不想让其 render 函数中的某个节点或者自身因为不相关的状态变化而去重新渲染造成性能上的浪费,可以使用useMemo来解决这个问题。
7.使用注意点
使用 useMemo
时需要注意以下几个重要的方面:
-
「性能优化的平衡」:不要滥用
useMemo
。只有在有昂贵的计算或大型引用类型传递给子组件时,才考虑使用它。过度使用useMemo
可能会导致不必要的复杂性和性能问题。 -
「正确选择依赖项」:确保依赖数组包含了所有在计算函数中使用的变量。如果忘记包含某个依赖,可能导致缓存的值不会在依赖变化时重新计算。
-
「依赖项是否需要深层比较」:注意依赖项是否是引用类型(如对象或数组)。如果依赖项是引用类型,它们的内容可能在地址不变的情况下发生变化。在这种情况下,你可能需要自行处理深层比较,以确保正确触发重新计算。
-
「避免不必要的内存占用」:虽然
useMemo
可以用于缓存引用类型,但要小心不要在不需要的情况下缓存大型对象或数组,以避免不必要的内存占用。在某些情况下,直接传递引用类型的变化可能更合适。 -
「记住
useMemo
返回的是值」:useMemo
返回的是计算的值,而不是函数。如果需要缓存函数,应该使用useCallback
。 -
「性能监控工具」:使用性能监控工具(如 React DevTools)来检查
useMemo
缓存的值是否按预期工作。这有助于排除性能问题和调试问题。 -
「组件层次结构考虑」:
useMemo
只在当前组件内有效。如果需要在多个组件之间共享缓存值,可能需要提升状态或使用上下文(Context)。
欢迎点赞、关注、转发~
本文由 mdnice 多平台发布