throttle & debounce ํด๋ฆฌํ
throttle๊ณผ debounce๋ ์ด๋ฒคํธํธ๋ค๋ง์ ๋นผ๋์ ์ ์๋ ์์์ด๋ค. ๊ฒ์๊ธฐ๋ฅ์ด๋ ์คํฌ๋กค ์ด๋ฒคํธ์ ๊ฐ์ด ์์ญ๋ฒ์ ์ฝ๋ฐฑ์ด ๋จ ์๊ฐ์ ํธ์ถ๋๋ ์ด๋ฒคํธ๋ฅผ ํธ๋ค๋งํ ๋ ์ฌ์ฉํ๋ค. ์ฃผ๋ก lodash์์ ๋ถ๋ฌ์ ์ฌ์ฉํ๊ณค ํ์ง๋ง, ๊ฐ๋
์ ์ดํดํ๊ธฐ ์ํด ์ง์ ๋ง๋ค์ด ๋ณด์๋ค. lodash์๋ tailing
๊ณผย leading
์ต์
์ด ์์ง๋ง ์ฌ๊ธฐ์๋ ์๋ตํ์๋ค. (์ฌ์ค ์์ด๋ false
๋ก ํด๋จ๋ ์ ์ด ๋๋ถ๋ถ์ด๋ผ..)
throttle
throttle์ ์ค์ ํ ์๊ฐ(delay)์ ํ๋ฒ์ฉ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํจ๋ค. ๋ง์ฝ ์คํฌ๋กค ์ด๋ฒคํธ์ ์ฝ๋ฐฑ์ throttle ํจ์๋ก ๊ฐ์ธ๊ณ delay
๋ฅผ 1์ด๋ก ์ค์ ํ์๋, ์คํฌ๋กค์ 5์ด๋์ ๋์์์ด ์ด๋ํ๋ค๋ฉด, ์ฝ๋ฐฑ์ 5๋ฒ ํธ์ถ๋๋ค.
function throttle(fn, delay) {
var timer = null;
return function () {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function() {
fn.apply(context, args);
timer = null;
}, delay);
}
};
}
debounce
dobouce๋ ์ด๋ฒคํธ๊ฐ ๋๋๋ค ์ค์ ํ ์๊ฐ(delay)์ด ์ง๋์ผ ์ฝ๋ฐฑ์ด ์คํ๋๋ค. throttle๊ณผ ๋น์ทํด๋ณด์ด๋๋ฐ ๊ฒฐ์ ์ ์ผ๋ก ๋ค๋ฅธ์ ์ด ์๋ค. debounce๋ ์ด๋ฒคํธ๋ฅผ ๊ทธ๋ฃนํ ํ๋ค๋ ๊ฒ์ด๋ค. ๋ง์ฝ ์คํฌ๋กค ์ด๋ฒคํธ์ ์ฝ๋ฐฑ์ debounce๋ก ๊ฐ์ธ๊ณ delay
๋ฅผ 1์ด๋ก ์ค์ ํ์๋, ์คํฌ๋กค์ 5์ด๋์ ๋์์์ด ์ด๋ํ๋ค๋ฉด, ์ฝ๋ฐฑ์ 1๋ฒ ํธ์ถ๋๋ค. ์คํฌ๋กค์ ๋ฉ์ถ ๋ค 1์ด์์ ๋ค์ ์คํฌ๋กค์ ์์ง์ด๋ฉด ์ฝ๋ฐฑ์ด ์ผ์ด๋์ง ์๊ณ , 1์ด๊ฐ ์ง๋๋ฉด ์ฝ๋ฐฑ ํจ์๊ฐ ํธ์ถ๋๋ค.
function debounce(fn, delay) {
var timer;
return function() {
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(context, args);
}, delay);
}
}
โฏ๏ธ useDebounce
useDebounce
๋ ๋ฆฌ์กํธ16.9 ๋ฒ์ ์ ์ถ๊ฐ๋ useState
์ useEffect
๋ฅผ ์ฌ์ฉํด state์ ๋ณํ๋ฅผ debouncingํ๋ ์ปค์คํ
Hooks์ด๋ค.
import { useState, useEffect } from 'react';
export function useDebounce(value, delay) {
// ๋๋ฐ์ด์ค ํ ๊ฐ์ ๊ด๋ฆฌํ๊ธฐ์ํ ์ํ๊ฐ๊ณผ setterํจ์
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
// ๋๋ ์ด ์ดํ ๊ฐ์ ์
๋ฐ์ดํธํ๋ค.
const timer = setTimeout(() => {
setDebouncedValue(value);
}, delay);
// ๋๋ ์ด ๊ธฐ๊ฐ์ค์ valueํน์ delay๊ฐ์ด ์
๋ฐ์ดํธ ๋์๋ค๋ฉด ์ด(cleanup)ํจ์๋ฅผ ์คํํ๋ค.
return () => {
clearTimeout(timer);
};
},[value, delay]); // delay๊ฐ์ด๋ value๊ฐ์ด ์
๋ฐ์ดํธ ๋์๋ค๋ฉด ๋ค์ ํธ์ถํ๋ค.
return debouncedValue;
}
useDebounce
๋ฅผ ์ฌ์ฉํ SearchBar ์ปดํฌ๋ํธ์ด๋ค. keyword
์ํ๊ฐ์ด input์ ํตํด ๊ณ์ ๋ณ๊ฒฝ๋์ด useDebounce
๋ด์ value
๊ฐ์ด ๊ณ์ ์
๋ฐ์ดํธ ๋๋ฉด์ useEffect
์ ์ฝ๋ฐฑํจ์๊ฐ ๊ณ์ ์คํ๋๋ค. ์ด๋ ์ฝ๋ฐฑํจ์์ return๊ฐ์ผ๋ก clearTimeout
ํจ์๋ฅผ ๋ฃ์ด์ค ์ฝ๋ฐฑ์ด ์คํ๋๊ธฐ ์ง์ ์ ๋งค๋ฒ timer
๋ฅผ ํด๋ฆฌ์ดํ๋ค.
import React, { useState, useEffect } from 'react';
import { useDebounce } from 'client/hooks';
const SearchBar = props => {
const [keyword, setKeyword] = useState('');
const [canSearch, setCanSearch] = useState(false);
const debouncedKeyword = useDebounce(keyword, 250);
useEffect(() => {
if(debouncedKeyword && canSearch){
searchApi(debouncedKeyword);
}
}, [debouncedKeyword]);
}
์ฐธ์กฐ