Lodash에는 지정된 시간 간격에 함수가 한 번만 실행되도록 제한하는 throttle 기능이 존재합니다.
다음은 Lodash의 throttle를 사용한 코드입니다.
import React, { useEffect, useRef, useState } from "react";
import { throttle } from "lodash";
export default function App() {
const [value, setValue] = useState(0);
const throttled = useRef(
throttle((newValue) => console.log(newValue), 10000));
useEffect(() => throttled.current(value), [value]);
return <button onClick={() => setValue(value + 1)}>{value}</button>;
}
throttle는 실행하려는 함수를 지정된 시간 간격(밀리초)으로 호출합니다.
위 코드에서 밀리초를 10000으로 설정하였으므로 10초마다 한 번씩 실행됩니다.
throttle를 적용한 함수를 useRef Hook에 저장하여 throttled 함수를 throttled.current 값으로 설정합니다.
state가 변경되면, useEffect Callback에서 throttled 함수를 호출합니다.
버튼을 클릭하여 value의 값이 변경되면, 10초마다 함수가 실행되는 것을 console에서 확인할 수 있습니다.
위 코드에서 useRef를 useCallback Hook으로 교체할 수 있습니다.
import React, { useEffect, useCallback, useState } from "react";
import { throttle } from "lodash";
export default function App() {
const [value, setValue] = useState(0);
const throttled = useCallback(
throttle((newValue) => console.log(newValue), 10000),
[]
);
useEffect(() => throttled(value), [value]);
return <button onClick={() => setValue(value + 1)}>{value}</button>;
}
디바운싱 함수는 useCallback Hook를 사용하여 자체적으로 구현할 수 있습니다.
useCallback으로 감싸줘야 한다.
import React, { useCallback, useEffect, useState } from "react";
const useDebouncedEffect = (func, delay, deps) => {
const callback = useCallback(func, deps);
useEffect(() => {
const timer = setTimeout(() => {
callback();
}, delay);
return () => {
clearTimeout(timer);
};
}, [callback, delay]);
};
export default function App() {
const [value, setValue] = useState(0);
useDebouncedEffect(() => console.log(value), 1000, [value]);
return <button onClick={() => setValue(value + 1)}>{value}</button>;
}
프로젝트 예시
components > table > productionInformation
const debounce = useCallback(debounceGenerator(400), [])
export const debounceGenerator = (ms) => {
let id
return (cb) => {
if (id) {
clearTimeout(id)
}
id = setTimeout(() => {
cb()
id = null
}, ms)
}
}
자체적으로 구현한 useDebounceEffect() 함수를 호출하여 useEffect Callback에 setTimeout() 함수를 호출합니다.
특정 시간 후 호출되어야 하는 함수는 useDebounceEffect() 함수에 첫 번째 인자로 전달합니다.
deps는 콜백의 의존성이며, 콜백의 의존성이 변경되었을 때에만 useCallback이 함수(func)를 변경합니다.
즉, useCallback Hook의 두 번째 인자인 deps의 값이 변경되면, 첫 번째 인자인 함수(func)를 재생성합니다.
setTimeout() 함수는 특정 시간이 지난 후 콜백을 실행합니다.
특정 시간이 지나지 않았는데, 함수가 다시 호출되는 경우 clearTimeout() 함수는 setTimeout()을 취소합니다.
src > components > domain > TagSearhModal > TagSearchModal > TagSearchModal
useEffect(() => {
if (!tags) {
return
}
if (!keyword.length) {
setFilteredTags(tags)
return
}
debounce(() => {
setFilteredTags(() => tags.filter((tag) => tag.includes(keyword))) // 키워드 검색
})
}, [tags, keyword])