防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
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)
}
节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。
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);
}
备注:createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。
每次组件重新渲染,都会执行一遍所有的hooks,这样debounce高阶函数里面的timer就不能起到缓存的作用(每次重渲染都被置空)。timer不可靠,debounce的核心就被破坏了。使用useRef的目的就是为了解决这个问题。
useRef实现了React组件的缓存机制。
网友评论