useMemo()
问题场景:
即上述场景如果修改的是支持数和反对数的状态值supNum\oppNum,组件重新更新,执行依赖于两状态的ratio计算逻辑是没有问题的;但如果修改的是无关状态值x,组件依然重新更新,ratio计算逻辑依然执行,但其值事实上不受影响,相关逻辑本无需更新,如果计算逻辑比较复杂势必影响性能。
此时需要useMemo()进行计算缓存:
let xxx=useMemo(callback,[dependencies])
- 第一次渲染组件的时候,callback会执行
- 后期只有依赖的状态值发生改变,callback才会再执行
- 每一次会把callback执行的返回结果赋值给xxx
- useMemo具备‘计算缓存’,在依赖的状态值没有发生改变,callback没有触发执行的时候,xxx获取的是上一次计算出来的结果
let ratio = useMemo(() => {
console.log('ok');
let total = supNum + oppNum,
ratio = '--'
if (total > 0) ratio = (supNum / total * 100).toFixed(2) + '%'
return ratio
}, [supNum, oppNum])
useMemo()是一个优化的Hook函数,和Vue中的计算属性很相似。
- 如果函数组件中,有消耗性能、时间的计算操作,则尽可能用useMemo()缓存起来,设置对应的依赖。
- 这样可以保证的,当非依赖的状态发生改变,不会去处理一些没必要的操作,提高组件更新的速度。
useCallback()
问题场景:
函数每次更新,handle都会重新创建一个新的堆内存(创建一个新函数),这样内存开辟的特别多,但是对于handle方法来讲,第一次创建的handle方法和后续新创建的handle方法功能基本一致,意义不大。是否可以让后续新创建的handle方法依然使用第一次创建的handle方法的堆内存以减少堆内存的开辟?
此时可以使用useCallback()对函数进行处理:
const xxx=useCallback(callback,[dependencies])
- 组件第一次渲染,usecallback执行,创建一个函数‘usecallback’,赋值给xxx
- 组件后续每一次更新,判断依赖的状态值是否改变,如果改变,则重新创建新的函数堆,赋值给xxx;如果依赖的状态没有改变【或者没有设置依赖‘[]’】,则xxx获取的一直是第一个创建的函数堆,不会再创建新的函数出来。
- 或者说,基于useCallback,可以始终获取第一次创建函数的堆内存地址(或者说函数的引用)
const handle = useCallback(() => {
...
}, [])//第一次:0x001 第二次:0x001
简单来讲,useCallback可以保证,函数组件的每一次更新,不再把里面的小函数重新创建,用的都是第一次创建的。
useCallback不要乱用,并不是所有组件内部的函数,都拿其处理会更好
- 虽然减少了堆内存的开辟
- 但是useCallback本身也有自己的处理逻辑和缓存的机制,这个也消耗时间
需求场景:
父组件嵌套子组件,父组件要把一个内部的函数基于属性传递给子组件,此时传递的这个方法,我们基于useCallback处理一下会更好。
const Demo = function Demo() {
let [x, setX] = useState(0)
// const handle = () => { }//第一次:0x001 第二次:0x101 第三次:0x201...
const handle = useCallback(() => {
}, [])//第一次:0x001 第二次:0x001 第三次:0x001...
return <div className="vote-box">
<Child handle={
handle}></Child>
<div className="main">
<p>{
x}</p>
</</