112 lines
2.7 KiB
TypeScript
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])
|
|
}
|