React-hooks【三】useCallback与useMemo详解,搭配Memo使用

1、UseCallback

我们知道,react的hook组件再state和props发生改变时,会重新渲染组件,从而导致子组件也会被重新渲染,但有些时候,子组件的props和state值没有变化,子组件就没必要重新渲染,因为如果子组件是一个大型的组件树,这种情况下虚拟DOM(Virtual Dom)的比较明显是很浪费资源的,此时就可以进行优化。在我的上一篇博客中有写到,Memo的作用,可以使用React.memo函数包裹子组件,这样在传递给子组件的 props 的值没有改变时,子组件就不会重新渲染。

// 父组件
const Father = () => {
	const [value, setValue] = useState(0)
	const changeValue = () => {
		setValue(value => value + 1)
	}
	return (
		<div>
			<Child value={value} changeValue={changeValue}>
		</div>
	)
}

// 子组件
const Child = ({value, changeValue}) => {
	console.log('子组件渲染了')
	return (
		<>
			<button onClick={changeValue}>改变数据</>
			<p>{value}</p>
		</>
	)
}

但是当子组件中的props中还存在函数属性changeValue时,当父组件重新渲染的时候,会生成一个新的函数对象cahngeValue,从而导致传入子组件的changeValue 对象发生改变,引起子组件重新渲染。

我们是不希望父组件中changeVlaue函数重新生成的,第一,它在重新渲染时没有什么改变;第二,它重新生成会导致子组件被重新渲染。所以我们可以把这个函数的功能缓存下来,每次使用缓存的函数,就不会导致重新渲染,useCallback因此而生。

useCallback 缓存的是函数。把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。否则在组件重新渲染的时候,该函数也不会重新生成,而是采用已经缓存的版本,故不会导致重新渲染。

看下面代码解释:

// 会缓存函数状态,函数不会改变,函数中的value值永远也不会改变,是初始值缓存的状态
const changeValue= useCallback(() => {
	setValue(value => value + 1)
}, [])

// 会缓存函数状态,在value改变时,改变函数状态,函数中value值也会变
// 注意:如果useCallback中函数使用到了父组件state中的值,一定要放在依赖数组中,比如value
const changeValue= useCallback(() => {
	setValue(value => value + 1)
}, [value])

// 不会缓存函数,每次组件重新渲染时都会重新生成一个新的 changeValue 函数对象,引起props变化,渲染子组件
const changeValue = () => {
	setValue(value => value + 1)
}

一般情况下,useCallback 函数是配合 memo 函数一起使用的,利用缓存函数使子组件不会重新渲染,如果不使用 React.meomo() 函数,子组件是会重新渲染的。

注意:
1、当依赖数组为空时,函数状态不会改变,是初始值时的状态
2、当依赖数组有值时,当该值变化时,函数状态改变,子组件重新渲染,该值不变化,函数状态不改变,子组件不会渲染

2、UseMemo

首先要区分 useMemomemo

useMemo 是一个hook

memo是一个高阶组件

useMemo 函数可以缓存已有的计算结果,在组件发生更新重新渲染时,会采用已有的缓存结果,而不是重新进行计算,从而达到性能优化的效果。

如果使用过Vue,就会发现,useMemoVue 中的 computed 类似。


// computeSum 值计算时比较占用性能的函数
// value, status 为依赖性,当 value 或 status 的值发生改变时,重新渲染的时候,会重新计算computeSum
// 这有助于避免每次重新渲染时都进行高开销的计算

const [value, setValue] = useState(100)
const [status, setStatus] = useState(200)

const computeSum = useMemo(() => {
	return value + status
}, [value, status])

注意:

传入 useMemo 的函数,会在渲染期间执行。不要在这个函数内部执行与渲染无关的操作,比如清除副作用。

如果没有提供依赖项数组,useMemo在每次渲染时都会计算新的值

useMemomemo 的优化方式,都是通过缓存的方式进行优化, React.memo 是高阶组件,通过包裹组件,可以让组件在只有 props 发生变化时(默认进行浅比较,第二个传参可以制定比较方式),才会重新渲染组件。

  • useMemo缓存的是值
  • useCallback缓存的是函数
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值