相同点:两者都是为了优化组件,减少组件的渲染使用
不同点:
- useCallback优化针对子组件的渲染
- useMemo优化针对于当前组件高开销的计算
关于useCallback
useCallback传入两个参数,回调函数(仅仅是一个函数) 和依赖参数
返回一个memorized回调函数,如果依赖参数没有改变,返回的回调函数是同一个引用地址,一般配合react.memo使用
例子: codesandbox.io/s/vibrant-r…
使用场景:父组件将一个方法传递给子组件,当父组件的其他状态发生改变时,子组件也会跟着重新渲染,useCallback能将父组件传递下来的函数缓存起来,只有useCallback的第二个参数改变时,才会重新创建函数实例
使用误区:
产生误区的缘由是useCallback的设计初衷并不是解决组件内部函数屡次建立的问题,而是减小子组件的没必要要重复渲染。
function Comp() {
const onClick = () => {
console.log('打印');
}
return <div onClick={onClick}>Comp组件</div>
}
当Comp组件自身触发刷新或做为子组件跟随父组件刷新时,咱们注意到onClick会被从新赋值。为了"提高性能",使用useCallback包裹onClick以达到缓存的目的:
import React, { useCallback } from 'react';
function Comp() {
const onClick = useCallback(() => {
console.log('打印');
}, []);
return <div onClick={onClick}>Comp组件</div>
}
此时并没有优化性能,反而使性能降低了
每一行多余代码的执行都产生消耗,哪怕这消耗只是 CPU 的一丁点热量。官方文档指出,无需担忧建立函数会致使性能问题,因此使用useCallback来改造该场景下的组件,咱们并未得到任何收益(函数仍是会被建立),反而其带来的成本让组件负重(须要对比依赖是否发生变化),useCallback用的越多,负重越多。站在 javascript 的角度,当组件刷新时,未被useCallback包裹的方法将被垃圾回收并从新定义,但被useCallback所制造的闭包将保持对回调函数和依赖项的引用。
关于useMemo
useMemo传入两个参数,回调函数(需要有返回值) 和依赖参数
返回一个memorirzd值,在依赖参数不发生改变的情况下,依旧返回上一次的值
注意 当依赖参数发生改变,会重新计算,返回一个新的值
useMemo使用场景:当组件内有开销很大的函数计算,此时可以用useMemo
useEffect和 useMemo useCallback的区别
useEffect可以帮助我们在DOM更新完成后执行某些副作用操作,如数据获取,设置订阅以及手动更改react 组件中的 DOM 等
有了useEffect,我们可以在函数组件中实现 像类组件中的生命周期那样某个阶段做某件事情,具有:
- componentDidMount
- componentDidUpdate
- componentWillUnmount
useCallback 和 useMemo 都是性能优化的手段,类似于类组件中的 shouldComponentUpdate,在子组件中使用 shouldComponentUpdate, 判定该组件的 props 和 state 是否有变化,从而避免每次父组件render时都去重新渲染子组件
useEffect是在DOM改变之后触发,useMemo在DOM重新渲染之前就触发 useEffect设置值会再次重新渲染,但useMemo不会