React.js中useMemo钩子是否会同时缓存对象的引用?
问题解答
是的,你的测试验证的结论完全正确,useMemo不仅会缓存原始类型的计算值,也会直接缓存引用类型的引用。
你之前看到的useMemo定义里的「缓存计算结果」从来没有限定只能缓存原始类型:
useMemo(compute, dependencies)会调用compute,缓存计算结果,再返回给组件。如果后续渲染时依赖没有变化,useMemo()不会重新调用compute,而是直接返回已经缓存的值。
—— Dmitri Pavlutin
这里的「值」完全遵循JavaScript的取值规则:如果返回的是字符串、数字这类原始类型,缓存的就是原始值本身;如果返回的是对象、数组、函数这类引用类型,缓存的就是对应内存空间的引用地址。
你测试中出现的现象逻辑非常清晰:
- 没有用
useMemo包裹时,App组件每次触发重渲染(点击按钮修改toggle状态时),都会重新执行{ bar: 'foo' },生成一个全新的对象,引用地址每次都不同。React.memo对子组件props做浅比较时,判断obj属性的引用发生了变化,因此会触发子组件重渲染,控制台每次都打印日志。 - 用
useMemo包裹且依赖项为空数组时,compute函数只会在App组件首次渲染时执行一次,生成一个对象,之后App的所有重渲染都会直接返回第一次缓存的对象引用,引用地址始终不变。React.memo浅比较判断obj属性没有变化,子组件就不会重渲染,因此只有首次渲染时会打印日志。
这个特性也是日常开发中useMemo的常见使用场景:固定引用类型的props,避免被React.memo包裹的子组件做不必要的重渲染,或者避免useEffect、useCallback等钩子因为引用类型的依赖频繁触发执行。
内容的提问来源于stack exchange,提问作者GoonGamja
相关产品推荐
相关产品推荐

