[react] throttle과 debounce

Ell!·2021년 12월 19일
1

react

목록 보기
18/28

문제점

input의 onChange에 전체 컴포넌트가 re-rendering된다?

스크림도르의 성향 태그 추가 모달을 리팩토링하던 중 searchWord라는 state의 onChange에 따라 전체 컴포넌트가 리랜더링되는 것을 확인했다.

최적화를 위해서 방법은 찾아봐야하는 상황. 이것저것 시도해보기 시작했다.

해결 방법

onChange에 debounce를 걸어보는 것은 어떨까?

가장 먼저 들었던 생각이다. onChange 자체에 debounce를 걸어서 리랜더링의 횟수를 줄여보는 것은 어떨까한 것이다.

// before
<input onChange={(e) => setSearchWord(e.target.value)} />

// after
<input onChange={(e) => _.debounce(setSearchWord(e.target.value),1500)} />

요렇게 바꾸어 보았다.

잘 되는 것 같았지만 이내 이런 에러가 뜬다.

아니? 나는 함수를 넘겼다고 생각했는데?? 결과적으로는 아니었따.

//simple debounce implementation
const debounce = (fn, delay = 50) => {
  let time;
  return (...args) => {
    clearTimeout(time);
    time = setTimeout(() => fn(...args), delay);
  };
};

debounce 함수는 간단하게 위와 같은 형태를 취하고 있다. 우리가 onChange에 넘긴 setSearchWordundefined를 return한다. 따라서, debounce함수는 자기가 받은 것이 함수 형태가 아니라고 생각하는 것이다.

잘못 생각하고 있었던 것

이것저것 찾아보니 onChange자체에 debounce를 적용하려는 시도는 보이지 않았다. 혹시 내가 잘못된 방향으로 생각을 하고 있는 것 아닌가 하는 생각에 다른 검색을 해보니,

스택오버플로우에서 나랑 똑같은 질문을 한 글을 확인할 수 있었다.

https://stackoverflow.com/questions/46942476/avoid-constant-re-render-from-input-or-textarea-in-react-js

결론적으로 react에서 controlled input을 관리하는 방법이니 별도의 컴포넌트로 분리하라는 답변... 생각해보면 당연한 거였는 이상한데에 꽂혀서 인지하지 못하고 있었다..

throttle 사용법 (22.02.07 추가)

항상 react에서 throttle debounce 사용하는 방법이 헷갈린다..

throttle한 함수를 callback에 넣어두자..!

  const handleTouchMove = _.throttle(e => {
    console.log(e.touches[0]);
  }, 1000);

  const qwer = useCallback(handleTouchMove, [handleTouchMove]);

/* ... */

 <ContainerHeader
    ref={handle}
    onTouchStart={handleTouchStart}
    onTouchMove={qwer}
    onTouchEnd={handleTouchEnd}
 >

참조

https://stackoverflow.com/questions/23123138/perform-debounce-in-react-js?page=1&tab=votes#tab-top

https://stackoverflow.com/questions/46942476/avoid-constant-re-render-from-input-or-textarea-in-react-js

https://stackoverflow.com/questions/64820257/lodash-debounce-typeerror-expected-a-function-react

profile
더 나은 서비스를 고민하는 프론트엔드 개발자.

0개의 댓글