持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
记忆化
记忆化(Memoization),对于计算量大的函数,通过缓存它的返回值来节省计算时间,提升程序执行速度。 对于记忆化函数的调用者而言,存入缓存这件事本身就是一种副作用。useMemo 和 useCallback 做性能优化的原理就是记忆化,所以它们的本质和 useEffect 一样,都是在处理副作用。
useMemo
这个 Hook 接受两个参数,一个是工厂函数,另一个是依赖值数组,它的返回值就是执行工厂函数的返回值:
const fibRes = useMemo(() => fibonacci(a), [a]);
useMemo 的功能是为工厂函数返回一个记忆化的计算值,在两次渲染之间,只有依赖值数组中的依赖值有变化时,该 Hook 才会调用工厂函数重新计算,将新的返回值记忆化并返回给组件。useMemo 最重要的使用场景,是将执行成本较高的计算结果存入缓存,通过减少重复计算来提升组件性能。
useCallback
它会把作为第一个参数的回调函数返回给组件,只要第二个参数依赖值数组的依赖项不改变,它就会保证一直返回同一个回调函数(引用),而不是新建一个函数,这也保证了回调函数的闭包也是不变的;相反,当依赖项改变时, useCallback 才会更新回调函数及其闭包。
const funcA = useCallback(() => {/*省略*/}, [a, b]);
其实 useCallback 是 useMemo 的一个马甲,相当于:
const funcA = useMemo(() => () => {/*省略*/}, [a, b]);
为什么说useCallback 能用来优化组件性能的呢?
举个例子:对于纯组件来说,当组件的 props 和 state 没有变化时,将跳过这次渲染。而在函数组件内频繁声明的事件处理函数,比如 handleSubmit ,在每次渲染时都会创建一个新函数。如果把这个函数随着 props 传递给作为子组件的纯组件,则会导致纯组件的优化无效,因为每次父组件重新渲染都会带着子组件一起重新渲染。这时就轮到useCallback 出马了,使用妥当的话,子组件不会盲目跟随父组件一起重新渲染,这样的话,反复渲染子组件的成本就节省下来了。
小结
本文主要介绍了用于性能优化的 Hooks:useMemo 和 useCallback。大家可以在评论区留下自己的优化方法!各位明天见!