[React] - 前端实现防抖、节流Demo(自定义 Hooks 封装)

全部 TS 版本,可直接复制到项目练习;每个 hook 附带使用示例。 注意点:清理副作用、组件卸载清除定时器、闭包陷阱、依赖处理

1. useDebounce 防抖

多次触发,等待一段时间没有再触发,才执行;输入搜索常用。

 1 import { useEffect, useState } from 'react'
 2 
 3 /**
 4  * 防抖值
 5  * @param value 需要防抖的值
 6  * @param delay 延迟 ms
 7  */
 8 function useDebounce<T>(value: T, delay: number): T {
 9   const [debouncedValue, setDebouncedValue] = useState<T>(value)
10 
11   useEffect(() => {
12     const timer = setTimeout(() => {
13       setDebouncedValue(value)
14     }, delay)
15 
16     // 组件卸载 / value变化 清除定时器
17     return () => {
18       clearTimeout(timer)
19     }
20   }, [value, delay])
21 
22   return debouncedValue
23 }
24 
25 // 📌 使用示例
26 function DemoDebounce() {
27   const [inputVal, setInputVal] = useState('')
28   const debounceVal = useDebounce(inputVal, 500)
29 
30   // debounceVal 500ms后才更新,用来发搜索请求
31   useEffect(() => {
32     if (debounceVal) {
33       console.log('发起搜索:', debounceVal)
34     }
35   }, [debounceVal])
36 
37   return <input value={inputVal} onChange={(e) => setInputVal(e.target.value)} placeholder="输入搜索" />
38 }

2. useThrottle 节流

固定时间内只执行一次;滚动、窗口 resize、按钮高频点击。

 1 import { useEffect, useRef, useState } from 'react'
 2 
 3 /**
 4  * 节流值
 5  * @param value
 6  * @param delay ms
 7  */
 8 function useThrottle<T>(value: T, delay: number): T {
 9   const [throttledValue, setThrottledValue] = useState<T>(value)
10   const lastExec = useRef<number>(0)
11 
12   useEffect(() => {
13     const now = Date.now()
14     if (now - lastExec.current >= delay) {
15       setThrottledValue(value)
16       lastExec.current = now
17     }
18   }, [value, delay])
19 
20   return throttledValue
21 }
22 
23 // 📌 使用示例
24 function DemoThrottle() {
25   const [scrollY, setScrollY] = useState(0)
26   const throttleY = useThrottle(scrollY, 200)
27 
28   useEffect(() => {
29     const handler = () => setScrollY(window.scrollY)
30     window.addEventListener('scroll', handler)
31     return () => window.removeEventListener('scroll', handler)
32   }, [])
33 
34   return <div style={{height:'150vh'}}>节流滚动位置:{throttleY}</div>
35 }

 

posted @ 2026-09-08 09:31  Kelly.Shi  阅读(3)  评论(0)    收藏  举报