[react] useDebounce hooks

dev stefanCho·2022년 1월 1일
1

react

목록 보기
16/19
post-custom-banner

검색어를 입력할 때는 debounce를 해야합니다.
입력할 때마다 api를 날리게 되면 성능저하 및 비용이 발생하기 떄문입니다.

Example

예제(codesandbox)코드를 보겠습니다.

import "./styles.css";
import { useState, useEffect } from "react";

function useDebounce(value, delay = 1000) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
}
export default function App() {
  const [inputValue, setInputValue] = useState("");
  const fetchValue = useDebounce(inputValue);
  const inputHandler = (e) => {
    setInputValue(e.target.value);
  };

  return (
    <div className="App">
      <input type="text" onChange={inputHandler} />
      <div>realtime Value: {inputValue}</div>
      <div>current Value: {fetchValue}</div>
    </div>
  );
}

첫번째 입력

useDebounce에서는 입력값, delay(옵션)을 받습니다.
입력값, delay 둘 중 하나라도 변하게 되면 useEffect를 실행합니다.
return의 함수는 다음 useEffect 호출때 실행됩니다.

n번째 입력

입력값 혹은 delay가 변하게 되면 useEffect가 실행되면서 먼저 이전의 useEffect의 clearTimeout을 하게 됩니다.

delay 시간 이내에 입력한 경우

이때 입력하고 1초내에 입력이 다시 들어온것이라면 clearTime에 의해서 그 전 setTimeout은 취소가 됩니다. (취소는 setTimeout의 id값을 보고 취소를 하는 것입니다. setTimeout은 number로 된 id를 return 합니다.)

// setTimeout의 return type은 number입니다.
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;

delay 시간이 지난 경우

만약 1초가 이미 지났다면 이미 실행이 끝난 것이기 때문에 clearTimeout이 하는것은 없습니다.

참고

참고로 위 예제는 단순히 debounce 활용에 대한 것이므로, 실제로 App컴포넌트 내에서는 useEffect로 검색에 대한 다른 처리들도 해줘야합니다. (예를 들어 debouncedValue가 빈 문자열인 상태이면 API를 날릴 필요가 없음)

Typescript

useDebounce에서 setTimeout 타입정의는 window를 앞에 붙여주면 브라우저의 setTimeout으로 바라 보게 됩니다. (window를 붙이지 않으면 Node의 setTimeout 타입으로 정의됩니다.)

import { useState, useEffect } from 'react';

export function useDebounce(value: any, delay = 500) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const handler = window.setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    return () => clearTimeout(handler);
  });

  return debouncedValue;
}

Ref

profile
Front-end Developer
post-custom-banner

0개의 댓글