或许大家都明白useCallback一个这样的作用,为了性能优化,但是怎么去用它才能达到性能优化呢,因为我曾经看到过有同事,碰到点击事件就用useCallback包裹起来,但是这样真的是能优化吗,今天我们就来捋一捋
useCallback(() => {}, [a, b]);
useCallback会返回一个函数的memoized值;
无依赖时,执行原来的函数;依赖项改变时,函数进行一个更新,在依赖不变的情况下,多次定义的时候,返回的值是相同的。
有些人可能会误以为 useCallback 可以用来解决创建函数造成的性能问题,其实恰恰相反,单从这个组件看的话 useCallback 只会更慢,因为 inline 函数是无论如何都会创建的,还增加了 useCallback 内部对 inputs 变化的检测。
我们先来看一段代码:
const add1= () => {
console.log("add1");
setCount(num+ 1);
}
const add2= useCallback(() => {
console.log("add2");
setNum(num+ 1);
}, [num])
1.当页面重新渲染时,会重新创建一个add函数
2.虽然我们add2用useCallback,但是页面重新渲染时,依然要执行useCallback后面的代码,只是返回的值相同,照样还是会创建一个函数
所以综上分析看来,这种情况下根本无法达到性能优化,我们千万不要掉进 useCallback 可以用来解决创建函数造成的性能问题的坑
那么,到底useCallback到底在什么时候用呢
场景:将父组件的函数,传给子组件作为回调使用时
export default function testCallBack() {
const [num, setNum] = useState(0);
const add1= () => {
setCount(num+ 1);
}
const add2= useCallback(() => {
setNum(num+ 1);
}, [num])
return (
<div>
<Son increment={add1} />
<Son increment={add2} />
</div>
)
}
const Son = memo((props) => {
console.log('子组件加载')
return <div onClick={props.add}>add1</div>
})
注意:memo:进行浅层比较,有更新就渲染,没更新不渲染,这里不过多阐述了
1.当父组件重新渲染时,父组件内add1重新创建,那传到子组件的时候,检测到有变化,所以渲染子组件
2.当父组件重新渲染时,父组件内也会add2重新创建,但是他使用了useCallback,依赖没有发生变化时,那useCallback就会返回相同的值,那add2的值就没有变化,memo检测到add2没有变化,就不更新子组件
以上就阐述完成useCalllback的用法和执行过程,得出结论:
useCallback的作用:配合memo用于优化子组件的渲染次数
下面在进行类组件同类问题的扩展上述代码,每次带你家ParentComponent就会导致ChildrenComponent也渲染一次,虽然ChildrenComponent采用了PureComponent 优化
在使用类组件的时候,使用不当,也会存在这样的问题
当父组件组件的setate发生改变的时候 render都会重新渲染一次,子组件的属性 handleChildren属性采用匿名函数赋值,导致每次的引用地址不一样,那么ChildrenComponent使用用PureComponent 优化是无效的
优化
<SonComponent
handleChildren={() => {
this.handleParent();
}}
/>
//替换成
<SonComponent handleChildren={this.handleParent()} />
点击父组件不会导致子组件也渲染,真正的起到了优化的作用
useMemo使用场景
优化针对于当前组件高开销的计算,具有记忆功能,
假如页面上有一个比较大的高开销的计算,每次set一个值的时候,都会重新执行计算函数,这样的话,很占内存,这时候可以用到useMemo
例如
// 假设computedNum()是一个计算量非常大的函数
const computeValue = useMemo(() => computedNum(num), [num]);
两者的区别
useCallback 对于子组件渲染优化
useMemo 对于当前组件高开销的计算优化
597

被折叠的 条评论
为什么被折叠?



