相信有不少React的初学者和我一样,对useCallback和use Memo并不太了解,恰好前几天的面试被问到了两者的区别,趁假期好好学习一下,顺便分享给有需要的同学。
官方文档描述
//useCallback
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
//useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback:把内联回调函数及依赖项数组作为参数传入 useCallback
,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate
)的子组件时,它将非常有用。
useMemo:把“创建”函数和依赖项数组作为参数传入 useMemo
,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。
记住,传入 useMemo
的函数会在渲染期间执行。请不要在这个函数内部执行不应该在渲染期间内执行的操作,诸如副作用这类的操作属于 useEffect
的适用范畴,而不是 useMemo
。
如果没有提供依赖项数组,useMemo
在每次渲染时都会计算新的值。
你可以把 useMemo
作为性能优化的手段,但不要把它当成语义上的保证。将来,React 可能会选择“遗忘”以前的一些 memoized 值,并在下次渲染时重新计算它们,比如为离屏组件释放内存。先编写在没有 useMemo
的情况下也可以执行的代码 —— 之后再在你的代码中添加 useMemo
,以达到优化性能的目的。
个人理解
从官方文档的描述,可以知道useCallback和useMemo这两者都是用来进行性能优化的,将原本每次都需要更新的部分改为只有当传入的依赖项改变时才更新。
并且,根据官方文档下给出的注意,两者的依赖数组都不会作为参数传给函数。
PS:useCallback(fn, deps)
相当于 useMemo(() => fn, deps)
也即useMemo传入高级函数(返回值为函数的函数)时,作用与useCallback类似
1.两者的区别
useCallback返回的是memoized(记忆化)的函数,而useMemo返回的是memoized(记忆化)的值,这与它们各自的应用场景有关。
2.useCallback作用
若依赖数组无变化则返回的函数不会更新
例子:考虑包含有一个子组件的父组件,且拥有两个state(记为s1与s2),子组件只与s1相关,在未使用useCallback时,无论s1、s2更新,子组件都需要更新,而使用依赖项为s1的useCallback来优化,则只有当s1更新时子组件才更新。
3.useMemo作用
保持一个高开销的函数的结果,只有当依赖数组变化时才更新这个结果
例子:考虑一个拥有两个state(仍记为s1与s2)组件,其中有一个很高开销的计算,但只与s1相关,当未使用useMemo时,无论s1、s2变化,他都会重新计算,浪费资源。使用依赖项为s1的useMemo优化后,仅当s1变化才会重新计算。