A React hook to throttle function calls, limiting execution frequency.
import { useEffect, useRef, useState } from 'react';
export function useThrottle<T>(value: T, delay: number): T {
const [throttledValue, setThrottledValue] = useState(value);
const lastRan = useRef(Date.now());
useEffect(() => {
const handler = setTimeout(() => {
if (Date.now() - lastRan.current >= delay) {
setThrottledValue(value);
lastRan.current = Date.now();
}
}, delay - (Date.now() - lastRan.current));
return () => clearTimeout(handler);
}, [value, delay]);
return throttledValue;
}Throttling is similar to debouncing, but instead of waiting for a pause, it ensures a function is called at most once per specified time period. This is useful for events that fire frequently, like scroll or resize.
import { useEffect, useRef, useState } from 'react';
export function useThrottle<T>(value: T, delay: number): T {
const [throttledValue, setThrottledValue] = useState(value);
const lastRan = useRef(Date.now());
useEffect(() => {
const handler = setTimeout(() => {
if (Date.now() - lastRan.current >= delay) {
setThrottledValue(value);
lastRan.current = Date.now();
}
}, delay - (Date.now() - lastRan.current));
return () => clearTimeout(handler);
}, [value, delay]);
return throttledValue;
}
lastRan tracks the last time the value was updated.function ScrollComponent() {
const [scrollY, setScrollY] = useState(0);
const throttledScrollY = useThrottle(scrollY, 100);
useEffect(() => {
const handleScroll = () => setScrollY(window.scrollY);
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// This will only update every 100ms, even if scroll fires more frequently
useEffect(() => {
console.log('Throttled scroll position:', throttledScrollY);
}, [throttledScrollY]);
}
Throttling is perfect for scenarios where you need consistent, periodic updates rather than waiting for a pause in activity.