useMemo和useCallback是React的内置Hook,通常作为优化性能的手段被使用,他们可以用来缓存函数、组件、变量,避免两次渲染间的重复计算,但是在实际使用中,他们经常被过度使用:担心性能的开发着给每个组件、函数、变量、计算都套上了memo,以至于他们在代码里好像失控了一样,无处不在
为什么要使用useMemo和useCallback
防止不必要的effect
防止不必要的render
防止不必要的重复计算
如果一个值被useEffect依赖,那么它可能需要被缓存,这样可以避免重复执行effect
当变量直接或者通过依赖链成为了useEffect的依赖项时,那它可能需要被缓存,这是useMemo和useCallback的最基本的用法
正确的阻止render需要我们明确三个问题:
三种情况:
当本身的props或者state改变时
Contextvalue改变时,使用该值的组件会render
当父组件重新渲染时,它所有的子组件都会render,形成一条render链
如何防止子组件render?
只有当子组件被React.memo包裹并且所有参数被useMemo缓存才能防止子组件render
为了防止子组件的render,需要一下成本:
开发着工作量的增加:一旦使用了缓存,就必须保证组件本身以及所有的props缓存,后续添加的props都要缓存
代码复杂度和可读性的变化,代码照中出现了大量缓存函数,这会增加代码复杂度,并降低易读性
性能成本:组件的缓存是在初始化时进行的,虽然每个组件缓存的性能耗费很低,通常不足1ms,但是大型程序中的组件初始化缓存,成本还是很高的
React dev tools profiler
useRenderTimes
16.5版本提出的Profiler API
useMemo主要用于缓存计算结果,适用于任何需要缓存值的场景
useCallback主要用于缓存回调函数,适用于需要传递给子组件的事件处理函数,以避免不需要的重新渲染