React 防抖 Hook: useDebounce 实现原理详解
React 防抖 Hook: useDebounce 实现原理详解
本文将详细解析 React 防抖 Hook (useDebounce) 的实现原理,并提供代码注释,帮助你理解防抖机制以及在 React 开发中如何使用 useDebounce Hook。
代码实现:
import { useEffect, useCallback, useRef } from 'react';
function useDebounce(fn, delay) {
let { current } = useRef({ fn, timer: null });
useEffect(() => {
current.fn = fn;
}, [current, fn]);
return useCallback(function f(...args) {
if (current.timer) {
clearTimeout(current.timer);
}
current.timer = setTimeout(() => {
current.fn.call(this, ...args);
}, delay);
}, [current, delay]);
}
export default useDebounce;
代码解释:
-
import { useEffect, useCallback, useRef } from 'react';- 引入 React Hooks,
useEffect用于处理副作用,useCallback用于记忆回调函数,useRef用于创建可变引用。
- 引入 React Hooks,
-
function useDebounce(fn, delay) {- 定义自定义 Hook
useDebounce,接收两个参数:fn: 要执行的函数delay: 延迟时间
- 定义自定义 Hook
-
let { current } = useRef({ fn, timer: null });-
使用
useRef创建一个对象,包含两个属性:fn: 保存传入的函数timer: 保存定时器 ID,初始值为null
-
使用解构赋值将
current属性从对象中提取出来。
-
-
useEffect(() => { current.fn = fn; }, [current, fn]);- 使用
useEffect监听fn和current的变化。 - 当
fn发生变化时,将新的fn赋值给current.fn。 - 依赖项
[current, fn]保证在fn或current改变时才会执行useEffect。
- 使用
-
return useCallback(function f(...args) { ... }, [current, delay]);- 返回一个回调函数
f,使用useCallback包裹,避免在每次渲染时创建新的回调函数。
- 返回一个回调函数
-
if (current.timer) { clearTimeout(current.timer); }- 如果当前计时器已存在,则清除计时器,防止重复执行。
-
current.timer = setTimeout(() => { current.fn.call(this, ...args); }, delay);- 设置一个新的计时器,延迟时间为
delay。 - 当计时器结束时,执行
current.fn函数,并将参数args传递给它。 - 使用
call方法确保current.fn在正确的this上下文中执行。
- 设置一个新的计时器,延迟时间为
-
[current, delay]- 将回调函数
f、current和delay作为依赖项,以确保每次渲染时返回的都是同一个回调函数,而不是新的引用。
- 将回调函数
-
export default useDebounce;- 导出自定义 Hook
useDebounce。
- 导出自定义 Hook
总结:
useDebounce Hook 实现防抖机制,它接收要执行的函数和延迟时间作为参数。当函数被调用时,它会先清除之前的计时器,然后设置一个新的计时器。当计时器结束时,才会执行传入的函数。这样就实现了防抖功能,防止函数在短时间内被多次调用。
使用方法:
import useDebounce from './useDebounce';
function MyComponent() {
const debouncedInputChange = useDebounce(handleInputChange, 500); // 延迟 500 毫秒
// ...
return (
<input
onChange={(e) => debouncedInputChange(e.target.value)}
/>
);
}
在上述示例中,每次用户输入时都会调用 debouncedInputChange,而 debouncedInputChange 是一个防抖函数,它会延迟 500 毫秒才执行 handleInputChange 函数。这样就避免了在用户快速输入时频繁地触发 handleInputChange 函数,提升了用户体验。
原文地址: https://www.cveoy.top/t/topic/oeMD 著作权归作者所有。请勿转载和采集!