首要大敌,就是不必要的重复渲染。这是Hooks项目里最常见的性能瓶颈。咱们组件里的状态(State)一变,整个函数组件就会重新执行一遍。这本来没问题,但要是子组件也跟着瞎起哄,不管用到的数据变没变都重新渲染,那性能能好才怪。
染。但这里有个巨坑!如果你传了个回调函数给子组件,比如:
完了,父组件每次渲染,都是新创建的,Props在浅比较看来就是变了,直接失效。这就引出了我们的第二招。
第二招:useCallback 和 useMemo 双剑合璧
是用来缓存函数本身的。你把函数和依赖项数组传给它,它只在依赖项变化时返回新的函数,否则返回上一次缓存的函数。
现在,再传给子组件,就能正确工作了。
同理,是用来缓存计算结果的。比如有个耗时的计算:
它保证了只有在依赖项变化时,才重新执行那段复杂的计算,避免每次渲染都算一遍。
第三招:小心使用useEffect的依赖项
的依赖项数组如果写得不严谨,会导致effect频繁执行,轻则请求乱发,重则死循环。一定要确保数组里包含了effect内部所有用到的、会变化的state和props。如果某个函数是在effect内部定义的,或者它依赖于会变化的state/props,那它也应该被放到依赖里。有时候,为了稳定依赖项的身份,我们甚至需要结合和。
第四招:惰性初始State
如果你的初始State需要通过复杂计算得到,别直接写在的参数里:
应该传一个函数给,这个函数只会初始渲染时执行一次:
第五招:不可变数据与状态拆分
在更新状态时,务必保持不可变性。使用新的对象或数组,而不是直接修改原来的。这不仅是React的要求,也便于React做差异比较。另外,考虑状态的粒度。别把一堆不相关的数据放在一个大的State对象里。一个状态的变更会引起整个对象的更新,进而导致依赖这个对象任何一部分的组件都重新渲染。不如拆分成多个独立的State。
最后,也是压轴的一招:useRef的正确用法
返回的可变ref对象,其属性发生变化时,是不会触发组件重新渲染的!这个特性太有用了。除了拿来直接操作DOM节点,它还可以用来存储任何会变化,但你不想让它引起重新渲染的值,比如定时器的ID、上一次的某些状态值、或者在多次渲染之间共享的任意可变值。
总结一下,Hooks的性能优化核心思路就是"按需渲染"。、、是我们的三驾马车,用来避免子组件不必要的渲染和昂贵的计算。同时,写好的依赖,用好惰性初始State和细粒度的状态管理,再配上处理副作用数据,就能极大地提升应用的流畅度。光说不练假把式,大家赶紧在自己的项目里试试看,感受一下那种丝滑的提升。如果还有啥疑难杂症,欢迎在评论区交流,咱们一起进步!