리액트 디바운싱 간단 구현 - react debounce

SeoYng·2020년 11월 21일
33
post-thumbnail

💡   개념 및 필요성

🤔 input창을 사용할 때 onchange 이벤트나 scroll 이벤트등 한꺼번에 많이 일어나는 이벤트들을 처리하는 경우 최적화해줄 필요가 있다.

🧚 라이브러리를 사용할 수도 있지만 간단하니 디바운싱을 직접 구현해보자

  • 노션같이 onchange시 변경사항이 바로바로 저장되는 것을 원할 때 사용하고자 함.
  • input의 value값을 useState로 클라이언트에서는 바로바로 바꿔주고 (사용자가 뻐벅임?을 못느끼도록)
  • api호출은 입력을 마친 뒤 한번만 수행되게끔 하기위해 (실제 서버에 저장)

디바운싱(debouncing)

연이어 호출되는 함수들 중 마지막 함수(또는 제일 처음)만 호출하도록 하는 것

let timer;
document.querySelector('#input').addEventListener('input', () => 
  if (timer) { // 이전 요청의 timer가 남아있다면 지우기
    clearTimeout(timer);
  }
  timer = setTimeout(() => { // 초기설정 혹은 덮어쓰기
    //API 요청
  }, 400);
);

쓰로틀링(throttling)

마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 것
몇 밀리초에 한 번씩만 실행되게 제한을 두는 것

let timer;
document.querySelector('#input').addEventListener('input', () => 
  if (!timer) { // timer 없으면 실행
    timer = setTimeout(() => {
      timer = null; // 시간 지난 후 timer 해제
      // timer 해제 후 API 요청
    }, 400);
  });

🧚   리액트 디바운싱 간단 구현

📃 Parent.js

import { useState } from 'react';
// API
import { updateMemberById } from '../../lib/api/memberApi';

function parent() {
  
  // 데이터 관리
  const [memberState, setMemberState] = useState({
    member: null,
  });
  
  const [timer, setTimer] = useState(0); // 디바운싱 타이머

  const onChangeInputs = async evt => {
    ...
    setMemberState({ // client data는 바로 변경
      member: memberData,
    });
    ...
    // 디바운싱 - 마지막 호출만 적용 (put api)
    if (timer) {
      console.log('clear timer');
      clearTimeout(timer);
    }
    const newTimer = setTimeout(async () => {
      try {
        await updateMemberById(match.params.id, memberData);
      } catch (e) {
        console.error('error', e);
      }
    }, 800);
    setTimer(newTimer);
  };
  ...
  return (
      <Child
      onChangeInputs={onChangeInputs}
      memberState={memberState}
      />
  );
}

📃 Child.js

function child({ onChangeInputs, memberState }) {
  return (
    <Input
    name="introduction"
    value={memberState.member.introduction}
    onChange={onChangeInputs}
    />
  )
}

이렇게 적어주면 0.8초 안에 연속으로 들어온 이전 요청들은 clear되고 마지막 요청만 실행된다.

profile
Junior Web FE Developer

3개의 댓글

comment-user-thumbnail
2021년 3월 12일

감사합니다!

답글 달기
comment-user-thumbnail
2021년 6월 29일

감사합니다!

답글 달기
comment-user-thumbnail
2022년 9월 7일

좋은 정보 고맙습니다.

답글 달기