hook,什么,防抖函数?
Posted 前端e站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hook,什么,防抖函数?相关的知识,希望对你有一定的参考价值。
防抖(debounce)是前端经常用到的一个工具函数,也是在面试中常常被问到的一个问题。
防抖函数
经典的防抖函数:
function debounce(fn, ms)
let timer;
return function(...args)
if (timer)
clearTimeout(timer)
timer = setTimeout(() =>
fn(...args)
timer = null;
, ms);
react hooks版的防抖函数
export default function()
const [counter, setCounter] = useState(0);
const handleClick = useDebounce(function()
setCounter(counter + 1)
, 1000)
return <div style= padding: 30 >
<Button
onClick=handleClick
>click</Button>
<div>counter</div>
</div>
实际使用的时候,是这样的
export default function()
const [counter1, setCounter1] = useState(0);
const [counter2, setCounter2] = useState(0);
const handleClick = useDebounce(function()
console.count('click1')
setCounter1(counter1 + 1)
, 500)
useEffect(function()
const t = setInterval(() =>
setCounter2(x => x + 1)
, 500);
return clearInterval.bind(undefined, t)
, [])
return <div style= padding: 30 >
<Button
onClick=function()
handleClick()
>click</Button>
<div>counter1</div>
<div>counter2</div>
</div>
当引入一个自动累加counter2就开始出问题了。这时很多候选人就开始懵了,有的候选人会尝试分析原因。只有深刻理解react hooks在重渲染时的工作原理才能快速定位到问题(事实上出错不要紧,能够快速定位问题的小伙伴才是我们苦苦寻找的)。
你可能会这样修改
const handleClick = useDebounce(function()
console.count('click1')
setCounter1(x => x + 1)
, 500)
还可能这样修改
function useDebounce(fn, delay)
return useCallback(debounce(fn, delay), [])
在配合setCounter1(x => x + 1)
修改的情况下,可以得到正确的结果。
但显然你仔细测试一下,还是没有真正的解决问题。
那么,问题在哪里呢?
function useDebounce(fn, time)
console.log('usedebounce') // 打印这里看一下
return debounce(fn, time);
控制台开始疯狂的输出log...,大脑在飞快的思考。
每次组件重新渲染,都会执行一遍所有的hooks,这样debounce高阶函数里面的timer就不能起到缓存的作用(每次重渲染都被置空)。timer不可靠,debounce的核心就被破坏了。
这才是优化
// 加入缓存机制
function useDebounce(fn, delay, dep = [])
const current = useRef( fn, timer: null );
useEffect(function ()
current.fn = fn;
, [fn]);
return useCallback(function f(...args)
if (current.timer)
clearTimeout(current.timer);
current.timer = setTimeout(() =>
current.fn.call(this, ...args);
, delay);
, dep)
//
function useThrottle(fn, delay, dep = [])
const current = useRef( fn, timer: null );
useEffect(function ()
current.fn = fn;
, [fn]);
return useCallback(function f(...args)
if (!current.timer)
current.timer = setTimeout(() =>
delete current.timer;
, delay);
current.fn.call(this, ...args);
, dep);
react hooks可以帮助我们把一些常用的状态逻辑沉淀下来,你学会了吗?
以上是关于hook,什么,防抖函数?的主要内容,如果未能解决你的问题,请参考以下文章
useEffect中防抖为什么不起作用?react hooks中如何写防抖?
useEffect中防抖为什么不起作用?react hooks中如何写防抖?