useThrottle
빠르게 변경되는 값을 일정 시간 간격으로만 업데이트하는 커스텀 훅ReactTypescript
예시
실제 값: -
스로틀된 값: -
500ms 동안 값이 변경되지 않으면 업데이트됩니다.
API
useThrottle<T>()- Parameters
- callback ((...args: Args) => Return)스로틀링할 콜백 함수
- limit (number)실행을 허용할 시간 간격(ms)
- Returns
- (...args: Args) => Return | undefined (function)스로틀링된 함수. 이 함수는 원본 함수와 동일한 매개변수를 받지만, limit 시간 간격으로만 실행됩니다.
개발 및 사용환경
ReactTypescript사용법
1// 기본 사용
2const [value, setValue] = useState("");
3const [throttledValue, setThrottledValue] = useState(value);
4
5const handleChange = useThrottle((newValue: string) => {
6 setThrottledValue(newValue);
7}, 500);
8
9useEffect(() => {
10 handleChange(value);
11}, [value, handleChange]);
12
13// 스크롤 이벤트 스로틀링
14const handleScroll = useThrottle(() => {
15 console.log(window.scrollY);
16}, 100);
17
18useEffect(() => {
19 window.addEventListener("scroll", handleScroll);
20 return () => window.removeEventListener("scroll", handleScroll);
21}, [handleScroll]);
Hook
1import { useCallback, useRef } from "react";
2
3/**
4 * 콜백 함수를 일정 시간 간격으로만 실행하는 Hook
5 *
6 * 이 훅은 함수가 너무 자주 호출되는 것을 방지하여 성능을 최적화합니다.
7 * 예를 들어, 스크롤 이벤트나 리사이즈 이벤트와 같이 빠르게 연속으로 발생하는 이벤트를 처리할 때 유용합니다.
8 *
9 * @param callback - 스로틀링할 콜백 함수
10 * @param limit - 실행을 허용할 시간 간격(ms)
11 * - 0 이하: 경고 메시지 출력 후 즉시 실행
12 * - 양수: 지정된 간격으로만 실행
13 *
14 * @returns 스로틀링된 함수. 이 함수는 원본 함수와 동일한 매개변수를 받지만,
15 * limit 시간 간격으로만 실행됩니다.
16 */
17export function useThrottle<Args extends unknown[], Return>(
18 callback: (...args: Args) => Return,
19 limit: number
20): (...args: Args) => Return | undefined {
21 const lastRan = useRef(Date.now());
22 const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
23
24 return useCallback(
25 (...args: Args) => {
26 if (limit <= 0) {
27 console.warn("useThrottle: limit must be a positive number");
28 return callback(...args);
29 }
30
31 const now = Date.now();
32 const timeSinceLastRun = now - lastRan.current;
33
34 if (timeSinceLastRun >= limit) {
35 // 마지막 실행 후 limit 시간이 지났으면 즉시 실행
36 lastRan.current = now;
37 return callback(...args);
38 } else {
39 // 아직 limit 시간이 지나지 않았으면 나머지 시간만큼 대기 후 실행
40 if (timeoutRef.current) {
41 clearTimeout(timeoutRef.current);
42 }
43
44 timeoutRef.current = setTimeout(() => {
45 lastRan.current = Date.now();
46 callback(...args);
47 }, limit - timeSinceLastRun);
48 }
49 },
50 [callback, limit]
51 );
52}