70 lines
No EOL
1.8 KiB
TypeScript
70 lines
No EOL
1.8 KiB
TypeScript
import { useState, useEffect } from "react"
|
|
|
|
export function useDebounce<T>(value: T, delay: number): T {
|
|
const [debouncedValue, setDebouncedValue] = useState<T>(value)
|
|
|
|
useEffect(() => {
|
|
const handler = setTimeout(() => {
|
|
setDebouncedValue(value)
|
|
}, delay)
|
|
|
|
return () => {
|
|
clearTimeout(handler)
|
|
}
|
|
}, [value, delay])
|
|
|
|
return debouncedValue
|
|
}
|
|
|
|
export function useLocalStorage<T>(key: string, initialValue: T) {
|
|
const [storedValue, setStoredValue] = useState<T>(() => {
|
|
if (typeof window === "undefined") {
|
|
return initialValue
|
|
}
|
|
try {
|
|
const item = window.localStorage.getItem(key)
|
|
return item ? JSON.parse(item) : initialValue
|
|
} catch (error) {
|
|
console.error(`Error reading localStorage key "${key}":`, error)
|
|
return initialValue
|
|
}
|
|
})
|
|
|
|
const setValue = (value: T | ((val: T) => T)) => {
|
|
try {
|
|
const valueToStore = value instanceof Function ? value(storedValue) : value
|
|
setStoredValue(valueToStore)
|
|
if (typeof window !== "undefined") {
|
|
window.localStorage.setItem(key, JSON.stringify(valueToStore))
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error setting localStorage key "${key}":`, error)
|
|
}
|
|
}
|
|
|
|
return [storedValue, setValue] as const
|
|
}
|
|
|
|
export function useIntersectionObserver(
|
|
elementRef: React.RefObject<Element>,
|
|
options: IntersectionObserverInit = {}
|
|
) {
|
|
const [isIntersecting, setIsIntersecting] = useState(false)
|
|
|
|
useEffect(() => {
|
|
const element = elementRef.current
|
|
if (!element) return
|
|
|
|
const observer = new IntersectionObserver(([entry]) => {
|
|
setIsIntersecting(entry.isIntersecting)
|
|
}, options)
|
|
|
|
observer.observe(element)
|
|
|
|
return () => {
|
|
observer.unobserve(element)
|
|
}
|
|
}, [elementRef, options])
|
|
|
|
return isIntersecting
|
|
} |