• 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>
    		</>
    	)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    但是当子组件中的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)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    一般情况下,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])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:

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

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

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

    • useMemo缓存的是值
    • useCallback缓存的是函数
  • 相关阅读:
    关于vue 组件 uni组件引用的原则
    1800亿参数,支持中文,3.5万亿训练数据!开源类ChatGPT模型
    抖音短视频实操:抖音热门视频的分类特点,如何选择视频内容并创作(下)
    文字生成图片
    字符串中第二大的数字(遍历)
    Raft 算法、分布式 KV 面试汇总
    Maya常见的3个问题,这么解决准没错
    spdk(一)----为什么要使用spdk?
    【力扣10天SQL入门】Day2
    python作业2
  • 原文地址:https://blog.csdn.net/qq_41131745/article/details/126031796