useCallback在什么时候使用?
场景:将一个组件中的函数,传递给子组件进行回调使用的时候,使用useCallback对函数进行处理
useCallBack实际的目的是为了进行性能优化;
如何进行性能优化呢?(基本上都配合memo使用)
react中当组件的props或者state变化时,会重新渲染视图,实际开发中会遇到不必要渲染的场景
子组件
function ChildComp () {
console.log('render child-comp ...')
return <div>Child Comp ...</div>
}
父组件
function ParentComp () {
const [ count, setCount ] = useState(0)
const increment = () => setCount(count + 1)
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<ChildComp />
</div>
);
}
当子组件(初次)重新载入,会打印console.log语句
点击父组件中的button组件,会修改count的值,进而导致整个父组件都会重新渲染,此时子组件理论上来说并不需要重新渲染,因为它并没有依赖任何父组件的值,但是现在它重新渲染了;
我们期待的结果:子组件的props或state没有发生变化的时候,即使父组件重新渲染,也不要重新渲染子组件;
修改子组件,用 React.memo() 包一层。
import React, { memo } from 'react'
const ChildComp = memo(function () {
console.log('render child-comp ...')
return <div>Child Comp ...</div>
})
上面的例子中,父组件只是简单的调用了子组件,并没有给子组件传递如任何的属性;如果给子组件传递了一些属性
子组件
import React, { memo } from 'react'
const ChildComp = memo(function ({ name, changeName}) {
console.log('render child-comp ...')
return <>
<div>Child Comp ... {name}</div>
<button onClick={() => changeName('hello')}>改变 name 值</button>
</>
})
父组件
function ParentComp () {
const [ count, setCount ] = useState(0)
const [ name, setName ] = useState('张三')
const changeName = (newName) => setName(newName)
return (
<div>
<button onClick={()=>{
setCount(count + 1)
}}>点击次数:{count}</button>
<ChildComp name={name} changeName={changeName}/>
</div>
);
}
当父组件的按钮发生了点击之后,子组件即使是在用memo包裹的情况下,依然会重新打印;
但是这是为什么呢?
父组件
function ParentComp () {
const [ count, setCount ] = useState(0)
const [ name, setName ] = useState('张三')
const changeName = useCallback((newName) => {
setName(newName)
},[])
return (
<div>
<button onClick={()=>{
setCount(count + 1)
}}>点击次数:{count}</button>
<ChildComp name={name} changeName={changeName}/>
</div>
);
}
此时点击父组件按钮,控制台不会打印子组件被渲染的信息了。
究其原因:useCallback() 起到了缓存的作用,即便父组件渲染了,useCallback() 包裹的函数也不会重新生成,会返回上一次的函数引用。