在使用 React 五年后,真正明白 useMemo 的意义

开发 前端
useMemo 是个用来“记住”某些计算结果的魔法,使得相同输入不会重复计算。虽然这种理解在技术层面没错,但用 useMemo 的更大收益在于确保引用(Reference)的稳定性。这在需要将某些数据传递给自定义 Hook 或作为依赖项使用时尤为重要。

刚接触 useMemo 时,我以为它的核心作用就是用来做缓存。很多开发者都有类似误解:认为 useMemo 主要是为了性能优化,以避免组件中不必要的重新计算。然而,经历了五年的 React 开发,我才意识到 useMemo 的真正价值不只是性能——更关键的是,它能保持数据引用的稳定性,让组件行为更加可预期。

为什么 useMemo 不仅仅是缓存

普遍的误解是:useMemo 是个用来“记住”某些计算结果的魔法,使得相同输入不会重复计算。虽然这种理解在技术层面没错,但用 useMemo 的更大收益在于确保引用(Reference)的稳定性。这在需要将某些数据传递给自定义 Hook 或作为依赖项使用时尤为重要。

设想一个场景:组件需要计算出某个对象,然后将这个对象当作参数传给自定义 Hook。如果这个对象在每次渲染时都新建一个实例,即使内容相同,引用也不同,从而导致 Hook 误以为数据每次都变了。这可能引发不必要的副作用或反复渲染。

我的经验教训:用对 useMemo

有一次,我在实现一个自定义计算 Hook 时遇到了类似问题。我在组件中内联构建了一个对象,把已有的 bookingFields 和 values 合并后传给 useCalculations:

const existingFields = {
    ...bookingFields,
    ...values,
};
const { calculations } = useCalculations(existingFields);

表面上看,这段代码似乎没啥问题。但不久后,我发现组件陷入了不停的重新渲染循环,计算结果也一直不稳定。问题的根源在于:虽然 existingFields 的内容没变,但每次渲染都会生成一个新的对象引用。React 在比较依赖项时是根据引用来判断变化的,所以自定义 Hook 认为数据“每次都更新了”。

拯救者 useMemo 登场

为了解决这个问题,我用 useMemo 将这个对象的创建过程包裹起来,让它只有在依赖数据(bookingFields 和 values)改变时才重新生成对象:

const existingFields = useMemo(
    () => ({
        ...bookingFields,
        ...values,
    }),
    [bookingFields, values]
);

改写之后,引用稳定下来,我的自定义 Hook 终于不再频繁触发重复计算,也不再让组件重复渲染。一切变得井然有序。🎉

何时使用 useMemo

  • 避免不必要的重渲染:当需要将派生出来的对象或数组作为依赖项传给自定义 Hook 或子组件时,可以用 useMemo 稳定它的引用,从而避免组件不断重新渲染。
    示例:有个子组件要接收一个数组作为 prop,用 useMemo 确保这个数组只有在源数据改变时才更新,而不是在每次父组件渲染时都生成新数组。
  • 稳定依赖:在 useEffect 或 useCallback 中使用依赖项时,如果这些依赖项是对象或函数引用,useMemo 能确保在依赖项未实际变动时不触发不必要的副作用。
  • 复杂计算:对于计算量较大的数据处理,useMemo 可以确保只有在相关依赖变动时才重新计算,减少性能浪费。

何时不该使用 useMemo

如果你的计算非常简单,或不依赖于外部动态数据,那么 useMemo 可能只是增加代码的复杂性,而无实质收益。不必要的 memo 化会使代码难以理解,并且可能没有明显的性能提升。

核心收获

useMemo 的真正价值在于保持引用的稳定性,进而保证组件行为的可预测性。当我们减少了无意义的重复计算和渲染,性能自然得以提升。但要记住,不要一上来就为了“优化”而过度使用 useMemo。清晰的思路是:先确保组件的行为正确、可控,然后在需要时再考虑用 useMemo 来避免不必要的变化。

下次你准备用 useMemo 时,不妨问问自己:是因为需要稳定数据引用以避免无谓的重复工作,还是只是在做无意义的“过早优化”?只有真正理解它的用武之地,才能让 useMemo 在你的 React 项目中发挥最大价值。

责任编辑:姜华 来源: 大迁世界
相关推荐

2009-10-22 20:48:28

IT管理统一通信

2016-04-13 10:52:12

2022-10-31 15:42:22

2009-03-04 09:59:04

职场心情痛苦

2013-12-03 10:30:32

2023-04-27 14:02:39

IT职业团队

2015-10-15 12:00:44

2009-07-21 11:17:08

云计算探索普及

2015-12-17 10:03:25

机器人就业上司

2023-04-07 00:08:20

IT职业AI自动化

2012-12-18 09:16:21

IBM计算机感官

2023-11-01 17:57:56

React应用程序性能

2020-07-08 15:13:04

开源技术 趋势

2018-04-26 18:25:11

华为

2019-10-30 10:42:42

CIO数字化转型开发

2015-10-08 11:33:32

物联网物联网设备

2016-03-04 16:22:23

WP微软移动

2020-09-14 15:30:23

开发技能代码

2023-11-28 16:19:17

GenAIOpenAI

2012-05-30 16:01:10

点赞
收藏

51CTO技术栈公众号