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提出来,作为相同的引用。