Files
chinese-family-tree-2/hooks/use-debounce.ts
T
freedakgmail fd9c064749 0.3.0.0
2025-11-30 09:16:43 +08:00

112 lines
2.7 KiB
TypeScript

'use client'
import { useState, useEffect, useCallback, useRef } from 'react'
/**
* 防抖值 Hook
* @param value 需要防抖的值
* @param delay 延迟时间(毫秒)
* @returns 防抖后的值
*/
export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(value)
}, delay)
return () => {
clearTimeout(timer)
}
}, [value, delay])
return debouncedValue
}
/**
* 防抖回调 Hook
* @param callback 需要防抖的回调函数
* @param delay 延迟时间(毫秒)
* @returns 防抖后的回调函数
*/
export function useDebouncedCallback<T extends (...args: any[]) => any>(
callback: T,
delay: number
): (...args: Parameters<T>) => void {
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
const callbackRef = useRef(callback)
// 保持回调函数的最新引用
useEffect(() => {
callbackRef.current = callback
}, [callback])
// 清理定时器
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
}
}, [])
return useCallback((...args: Parameters<T>) => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
timeoutRef.current = setTimeout(() => {
callbackRef.current(...args)
}, delay)
}, [delay])
}
/**
* 节流回调 Hook
* @param callback 需要节流的回调函数
* @param delay 延迟时间(毫秒)
* @returns 节流后的回调函数
*/
export function useThrottledCallback<T extends (...args: any[]) => any>(
callback: T,
delay: number
): (...args: Parameters<T>) => void {
const lastRunRef = useRef<number>(0)
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
const callbackRef = useRef(callback)
// 保持回调函数的最新引用
useEffect(() => {
callbackRef.current = callback
}, [callback])
// 清理定时器
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
}
}, [])
return useCallback((...args: Parameters<T>) => {
const now = Date.now()
const timeSinceLastRun = now - lastRunRef.current
if (timeSinceLastRun >= delay) {
lastRunRef.current = now
callbackRef.current(...args)
} else {
// 如果在节流期间,设置一个定时器在节流期结束后执行
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
timeoutRef.current = setTimeout(() => {
lastRunRef.current = Date.now()
callbackRef.current(...args)
}, delay - timeSinceLastRun)
}
}, [delay])
}