useCallback和useMemo的主要作用是用于性能优化。
一、useCallback
特点:1.接收两个参数,第一个参数是函数(需要缓存的函数),第二个参数是依赖项,只有依赖项改变之后,才会重新执行函数。
使用场景:当父组件传给子组件自定义事件,而子组件重新渲染时的性能消耗较大 ,此时使用useCallback可以尽量避免掉子组件的不必要渲染(注意:useCallback需要和React.memo搭配使用)。
下面的代码是为了实现这么一个效果:1.当父组件向子组件只传递一个属性时,因为子组件有React.memo的包裹,所以只要被子组件接收的属性(状态)没有改变(或者说更新),那么子组件就不会随着父组件的重新渲染而渲染。这样就避免了子组件的不必要的重新渲染,可以节省性能。2.当父组件向子组件传递函数(对象也适用,下同)的时候,因为函数是复杂数据类型(每次父组件重新渲染都会创建一个新的地址引用,就会认为需要将‘新’的函数传给子组件,实际上这个函数并不存在新旧之别 ),此时用useCallback将要传的函数包住,那么父组件重新渲染就不会引起子组件跟着重新渲染了。useCallback的第二个参数是一个依赖数组,数组里面存放的变量改变,那么就会引起子组件的重新渲染。
步骤一:定一个父组件,在里面定义好状态和事件以及需要向子组件传递的内容。
import React, { useCallback, useState } from 'react'
import Child from ‘./Child’
//................定义好一个父组件
const App = () => {
const [count,setCount] = useState(100)
const [name,setName] = useState('张三')
//................ 1. 父组件先定义修改的函数
let changeName = (val)=>{setName(val) }
//...........useCallback 将使用的函数包裹起来,可以将这些函数进行缓存
changeName = useCallback(changeName, [])
return (
<div >
<h1>{count}</h1>
<button onClick={()=>{setCount(count + 1)}}> 点击加 1 </button>
//................ 2. 将修改函数传递给子组件
//........向子组件传一个属性和一个事件函数。
<Child name={name} changeName={changeName} />
</div>
)
}
步骤二:定义一个子组件
import React, { useCallback, useState } from 'react'
//.............props接收父组件传过来的属性和事件
let Child = (props)=>{
return (<div>
Child --- {props.name}
<button onClick={()=>{
// 3. 在子组件中触发修改
props.changeName('李四')
}}>点击修改名称</button>
</div>)
}
//...........注意!!一定要用React.memo来包住子组件。
Child = React.memo(Child)
export default Child
二、useMemo
特点:1.接收两个参数,第一个参数是函数的返回值(需要缓存的函数),第二个参数是依赖项,只有依赖项改变之后,才会重新执行函数。
场景:当组件中有一个内部存在复杂运算的函数时(执行时性能消耗大),为了防止组件的重新渲染引起函数的重新执行,那么就用useMemo将该函数包住,将其返回值缓存起来。使用时当做属性使用 。
import React, {useMemo, useState } from 'react'
const App = () => {
const [count, setCount]=useState(1)
const total=useMemo(()=>{
let sum=0
for(let i=0;i<count*100;count++){
sum+=i;
//return计算结果
return sum
})
return (
<div >
total:{total}
</div>
)
}