useMemo和useCallback

200 阅读2分钟

memo是优化子组件的一种方式,类似于class组件的pureComponentment。 当父组件传给子组件的值,未发生改变时,子组件不会重新渲染。 memo和useMemo是没有关系的。 memo的使用就是把子组件包一层。

<Foo count={1}/>
=================
const Foo = memo((props) => {
    console.log('Foo render');
    return (
        <div>
        </div>
    )
})

首先明确一点,父组件传给子组件的方法,是一直都会变的。不是同一个方法。
当父组件传给子组件方法时,子组件就会随着父组件的更新,重新渲染。
既然方法一直会变,所以要想个办法,让方法是同一个引用,固定下来。
要用到useCallback
只需要用useCallback把方法给包起来,同时指定依赖项。 当依赖项改变时,才会导致子组件重新渲染。//我猜是因为方法不是同一引用了。

const render = useCallback(() => {
        const list = [];
        for(let i=0;i<range.max;i++) {
            list.push(<li key={i}>{i}</li>)
        }
        return list;
    },[range])

当依赖项为空数组时,什么时候都不会改变函数的引用,子组件永不会重新渲染。

useMemo和useCallback不同的是, useCallback保证是同一函数,useMemo保证是同一个值。

useMemo里面也是一个函数,函数本身和useCallback包裹的函数没有任何区别。

        const list = [];
        for(let i=0;i<range.max;i++) {
            list.push(<li key={i}>{i}</li>)
        }
        return list;
    },[range])

只是经过useMemo包裹后的render不再是函数,而是return的list。
所以在子组件里用到render,不再是{props.render()},而直接是{props.render}.

     做好区分两个东西:
  •      memo和useMemo
    

memo是用于对组件的优化,不会因为同样的参数而重新渲染;useMemo是固定值的

  •      useMemo和useCallback
    

官网上有句话是说, useCallback(fn,deps)相当于useMemo(()=>{fn()}, deps) 意思是说,useMemo的函数fn是要执行的,因为要把fnreturn的值赋值给fn;useCallback只是把fn提出来,作为相同的引用。