useMemo,useCallback,useEffect使用场景和区别

1,735 阅读3分钟

相同点:两者都是为了优化组件,减少组件的渲染使用

不同点

  1. useCallback优化针对子组件的渲染
  2. useMemo优化针对于当前组件高开销的计算

关于useCallback

useCallback传入两个参数,回调函数(仅仅是一个函数)依赖参数

返回一个memorized回调函数,如果依赖参数没有改变,返回的回调函数是同一个引用地址,一般配合react.memo使用

例子: codesandbox.io/s/vibrant-r…

使用场景:父组件将一个方法传递给子组件,当父组件的其他状态发生改变时,子组件也会跟着重新渲染,useCallback能将父组件传递下来的函数缓存起来,只有useCallback的第二个参数改变时,才会重新创建函数实例

使用误区:

产生误区的缘由是useCallback的设计初衷并不是解决组件内部函数屡次建立的问题,而是减小子组件的没必要要重复渲染

function Comp() {
    const onClick = () => {
        console.log('打印');
    }
    
    return <div onClick={onClick}>Comp组件</div>
}

Comp组件自身触发刷新或做为子组件跟随父组件刷新时,咱们注意到onClick会被从新赋值。为了"提高性能",使用useCallback包裹onClick以达到缓存的目的:

import React, { useCallback } from 'react';
​
function Comp() {
    const onClick = useCallback(() => {
        console.log('打印');
    }, []);
    
    return <div onClick={onClick}>Comp组件</div>
}

此时并没有优化性能,反而使性能降低了

每一行多余代码的执行都产生消耗,哪怕这消耗只是 CPU 的一丁点热量。官方文档指出,无需担忧建立函数会致使性能问题,因此使用useCallback来改造该场景下的组件,咱们并未得到任何收益(函数仍是会被建立),反而其带来的成本让组件负重(须要对比依赖是否发生变化),useCallback用的越多,负重越多。站在 javascript 的角度,当组件刷新时,未被useCallback包裹的方法将被垃圾回收并从新定义,但被useCallback所制造的闭包将保持对回调函数和依赖项的引用。

关于useMemo

useMemo传入两个参数,回调函数(需要有返回值)依赖参数

返回一个memorirzd,在依赖参数不发生改变的情况下,依旧返回上一次的值

注意 当依赖参数发生改变,会重新计算,返回一个新的值

useMemo使用场景:当组件内有开销很大的函数计算,此时可以用useMemo

useEffect和 useMemo useCallback的区别

useEffect可以帮助我们在DOM更新完成后执行某些副作用操作,如数据获取,设置订阅以及手动更改react 组件中的 DOM 等

有了useEffect,我们可以在函数组件中实现 像类组件中的生命周期那样某个阶段做某件事情,具有:

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

useCallback 和 useMemo 都是性能优化的手段,类似于类组件中的 shouldComponentUpdate,在子组件中使用 shouldComponentUpdate, 判定该组件的 props 和 state 是否有变化,从而避免每次父组件render时都去重新渲染子组件

useEffect是在DOM改变之后触发useMemoDOM重新渲染之前就触发 useEffect设置值会再次重新渲染,但useMemo不会