TypeScript에서 useDebounce, useThrottle 만들기

IT공부중·2020년 12월 10일
8

TypeScript

목록 보기
7/9

useDebounce와 useThrottle은 debounce와 throttle이 적용된 함수를 반환해주는 hook이다.

timer를 useRef로 하여 리렌더링 되도 timer가 초기화 되는 현상을 막는다.

callback 함수의 타입 추론을 잘하게 하기 위해서 <T extends any[]> 를 generic으로 받는다. 이렇게 하는 이유는 ...params 형태로 여러 개의 인자를 받을 수 있게 하기 위해서이다. callback 함수의 인자가 몇개가 들어올지 모르니 위 방식으로 해결하였다.

해당 hook은 둘 다 똑같이 callback과 time을 파라미터로 받는다.

debounce는 time 안에 함수가 한번더 실행되면 앞의 작업을 취소하고 time이 지날 때까지 다시 호출 되지 않으면 callback을 실행하는 형식으로 되어있다.

throttle은 time 뒤에 callback이 실행되고 time이 지나기전 다시 호출될 경우 아직 time이 지나지 않았기 때문에 callback을 실행하지 않고 함수를 종료시키는 형태로 되어있다.

코드는 다음과 같다. 이제 어떤 함수든 debounce 와 throttle을 적용할 수 있게 되었다.

useDebounce

import { useRef } from 'react';

function useDebounce<T extends any[]>(callback: (...params: T) => void, time: number) {
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
  return (...params: T) => {
    if (timer.current) clearTimeout(timer.current);

    timer.current = setTimeout(() => {
      callback(...params);
      timer.current = null;
    }, time);
  };
}

export default useDebounce;

useThrottle

import { useRef } from 'react';

function useThrottle<T extends any[]>(callback: (...params: T) => void, time: number) {
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);

  return (...params: T) => {
    if (!timer.current) {
      timer.current = setTimeout(() => {
        callback(...params);
        timer.current = null;
      }, time);
    }
  };
}

export default useThrottle;

실제 사용 예

const onScroll = (e: React.UIEvent<HTMLDivElement>) => {
    const target = e.target as HTMLDivElement;
    const scrollHeight = target.scrollHeight;
    const scrollTop = target.scrollTop;
    const clientHieght = target.clientHeight;

    if (scrollTop + clientHieght >= scrollHeight - 50 && maxNumber < allMenu.current.length) {
      setMaxNumber((number) => number + DISPLAY_INTERVAL);
    }
  };

  const throttleOnScroll = useThrottle<[React.UIEvent<HTMLDivElement>]>(onScroll, 300);

위에 callback으로 넘겨줄 함수를 정의해준다.

그리고 useThrottle을 실행해서 throttle이 적용된 함수를 받으면 된다. 중요한 것은 T에 들어갈 타입이다. callback으로 넘겨줄 함수의 파라미터 타입 순서대로 ( ex)<[type1, type2] 이런식) 적어주어야한다. 그러면 반환된 throttleOnScroll 함수에서도 타입 추론이 되는 것을 확인할 수 있을 것이다.

profile
4년차 프론트엔드 개발자 문건우입니다.

0개의 댓글