React useDebounce Hook 사용기

Gee·2022년 6월 26일
5
post-custom-banner

공부를 하면서 여러가지 레퍼런스 및 블로그를 보며 적은 글이라 틀린 부분이 있을수도 있습니다. 혹시 그런 부분이 있다면, 바로 잡아주시면 감사드립니다 :)

문제상황

여러번 버튼을 클릭했을 때, 마지막 클릭한 후 몇 초 후에 api를 호출할 수 있도록 debounce를 사용하여 문제상황을 해결하였다.

useDebounce 제작 🔨

import { useRef, useState } from 'react';

const useDebounce = (callback: () => void, term: number) => {
  const timer = useRef<ReturnType<typeof setTimeout>>(); //clearTimout 사용을 위해 timer이라는 변수를 생성

  const dispatchDebounce = () => {
    if (timer.current) {
      clearTimeout(timer.current);
    }
    const newTimer = setTimeout(() => {
      callback();
    }, term);
    timer.current = newTimer;
  };
  return dispatchDebounce;
};
export default useDebounce;

useDebounce의 인자값으로 callback 함수와 delay 시간을 받는다. 이후, 처음에는 newTimer가 생성되고 timer안에 newTimer를 담게 된다. 하지만, 이후 delay시간안에 여러번의 클릭으로 인해 함수가 호출된다면 다시 clearTimout을 통해 timer를 reset시킨다.

timer를 useState로 처음에 관리하다가 값이 바뀔때마다 랜더링되는 것을 막기 위해서 useRef로 수정하였다.

컴포넌트에 사용한 예시 살펴보기 !

저는 검색어 입력창에 해당 부분을 적용시켜보았습니다.

import React, { useEffect, useState } from 'react';
import useDebounce from 'utils/debounce-utils';

const DebounceTest = () => {
  const [likeStatus, setLikeState] = useState(false);

  const textFunction = () => {
    //api 호출할 함수
    if (likeStatus) {
      console.log('성공');
      return '성공';
    } else {
      console.log('실패');
      return '실패';
    }
  };
  const debouncedTextFunc = useDebounce(textFunction, 1000);
  
  useEffect(() => {
    debouncedTextFunc();
  }, [likeStatus]);

  const onClickLikeButton = () => {
    setLikeState((prev) => !prev);
  };

  return (
    <>
      <button
        style={
          likeStatus ? { backgroundColor: 'red' } : { backgroundColor: 'white' }
        }
        onClick={onClickLikeButton}
      >
        좋아요 버튼
      </button>
    </>
  );
};

export default DebounceTest;

좋아요 버튼을 클릭할 때마다 onClickLikeButton 함수로 인해 state값이 바뀌게되고,
바뀐값으로 인해 debouncedTextFunc 함수가 호출되게 된다.

결론

최근에 최적화에 관심을 갖게 되면서, 리렌더링을 줄일 수 있는 방법을 조금씩 모색하고 있다. 그러던 와중에 디바운스를 찾게 되었는데 꽤 유용해 보인다. lodash 사용하는 방법도 있는데 따로 사용하지 않고 직접 구현해보았다.

profile
작은 실패, 빠른 피드백, 다시 시도
post-custom-banner

0개의 댓글