참고 MDN

setTimeout 실행시 리턴되는 값은 timeoutID 입니다.

Untitled

  const [debounce, setDebounce] = useState(0); 

	function getDebounce(data: string) {
    if (debounce) window.clearTimeout(debounce);

    const time = window.setTimeout(() => {
      console.log("실행");
      refetch({ search: data });
      setSearch(data);
    }, 500);

    setDebounce(time);
  }

검색 키워드가 입력될 때마다 getDebounce 함수가 실행되고,

setTimeout을 이용해서 실제로 refetch가 실행되는건 500ms 뒤가 됩니다.

그런데 다시 검색창에 변화가 생겨 getDebounce가 실행되면 기존에 있던 Timeout을 지워주고,

새로 500ms 뒤에 refetch가 실행되도록 합니다. 이런 식으로 Timeout을 관리하기 위해 debounce라는 state를 만들어주었습니다.

적용된 코드는 아래와 같습니다.

export default function SearchPage() {
  const [search, setSearch] = useState("");
  const [debounce, setDebounce] = useState(0); // state 추가

  const { data, refetch } = useQuery<
    Pick<IQuery, "fetchBoards">,
    IQueryFetchBoardsArgs
  >(FETCH_BOARDS);

	// lodash의 디바운스
  // const getDebounce = _.debounce((data) => {
  //   refetch({ search: data });
  //   setSearch(data);
  // }, 500);

	// 직접 구현
  function getDebounce(data: string) {
    if (debounce) window.clearTimeout(debounce);

    const time = window.setTimeout(() => {
      console.log("실행");
      refetch({ search: data });
      setSearch(data);
    }, 500);

    setDebounce(time);
  }

  function onChangeSearch(event: ChangeEvent<HTMLInputElement>) {
    getDebounce(event.target.value);
  }

  function onClickPage(event: MouseEvent<HTMLSpanElement>) {
    refetch({ search: search, page: Number((event.target as Element).id) });
  }

  return (
    <>
      <input type="text" onChange={onChangeSearch} />
      {/* <button onClick={onClickSearch}>검색하기</button> */}
      {data?.fetchBoards.map((data) => (
        <div key={data._id}>
          <Column>{data.writer}</Column>
          <Column>{data.title}</Column>
          <Column>{data.createdAt}</Column>
        </div>
      ))}
      {new Array(10).fill(1).map((_, index) => (
        <Page key={index} id={String(index + 1)} onClick={onClickPage}>
          {index + 1}
        </Page>
      ))}
    </>
  );
}