个人对useMemo和useCallback的理解(附带节流,防抖)

297 阅读2分钟

本人已参与「新人创作礼」活动,一起开启掘金创作之路

对于useMemo和useCallback这两个hook,在日常中个人很少使用,一般都是在需要创建一个闭包的时候才使用,因为react的函数组件在每一次更新状态的时候,都是重新创建,如果不使用useMemo或者useCallback来缓存闭包,会导致运行的效果跟预计的不合。

useCallback和usememo都是有缓存的作用,个人认为区别在于useMemo返回的是函数运行的结果,useCallback返回的是函数。

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)
 const kao=()=>{
    let time=null
    return ()=>{
      if(time) return
      time=setTimeout(()=>{
        console.log(1)
        time=null
      },1000)
    }
  }
  const memo=useMemo(kao,[src1])
  const callback=useCallback(kao,[src1])
    <button onClick={()=>{
      console.log(memo)
      console.log(callback)
    }}>测试</button>

console.log(memo)打印的结果如下

() => {
      if (time) return;
      time = setTimeout(() => {
        console.log(1);
        time = null;
      }, 1000);
    }

console.log(callbacl)打印的结果如下

() => {
    let time = null;
    return () => {
      if (time) return;
      time = setTimeout(() => {
        console.log(1);
        time = null;
      }, 1000);
    };
  }

由此可见useMemo返回的是函数运行的结果,useCallback返回的是函数,同时也证明了useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

接下来,使用usememo来封装一个节流和防抖的hook

防抖(debounce): 将多次高频操作优化为只在最后一次执行,通常使用的场景是:用户连续输入,只需要在输入结束后做一次校验即可,比如input搜索,校验

const useDebounce=(val:any,time:any)=>{
    const [value,setValue]=React.useState(val)
    const deboun=React.useMemo(()=>{
        let tim:any=null
        return (e:any)=>{
            if(tim) clearTimeout(tim)
            tim=setTimeout(()=>{
                setValue(e)
            },time)
        }
    },[time])
    return [value,deboun]//使用数组的是因为不需要定义死参数
} 

使用

const Cs=()=>{
    const [value,setValue]=useDebounce('',300)
    return <input onChange={(e)=>setValue(e.target.value)}/>
}

节流(thorttle):每隔一段时间执行一次,也就是降低频率,将高频操作优化成低频操作。通常使用场景: 滚动条事件,窗口resize事件,通常每隔100-500ms执行一次

const useThrottle=(val:any,time:any)=>{
    const [value,setValue]=React.useState(val)
    const deboun=React.useMemo(()=>{
        let tim:any=null
        return (e:any)=>{
            if(time) return
            tim=setTimeout(()=>{
                setValue(e)
                time=null
            },time)
        }
    },[time])
    return [value,deboun]
} 
使用
const Cs=()=>{
    const [value,setValue]=useThrottle('',300)
    return <input onChange={(e)=>setValue(e.target.value)}/>
}