Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@sophister
Last active August 25, 2020 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sophister/9cc74bb7f0509bdd6e763edbbd21ba64 to your computer and use it in GitHub Desktop.
Save sophister/9cc74bb7f0509bdd6e763edbbd21ba64 to your computer and use it in GitHub Desktop.
React Hooks for debounce, useDebounce, useDebounceState, with cleanup surpport
import { useState, useEffect, useRef, useCallback } from "react";
export function useDebounceState<T>(initValue: T, delay: number) {
const [value, setValue] = useState<T>(initValue);
const timerRef = useRef(null);
// reset timer when delay changes
useEffect(
function () {
if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = null;
}
},
[delay]
);
const debounceSetValue = useCallback(
function (val) {
if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = null;
}
timerRef.current = setTimeout(function () {
setValue(val);
}, delay);
},
[delay]
);
return [value, debounceSetValue];
}
interface DebounceOptions {
imediate?: boolean;
initArgs?: any[];
}
const INIT_VALUE = -1;
export function useDebounce(fn, delay: number, options: DebounceOptions = {}) {
const [num, setNum] = useDebounceState(INIT_VALUE, delay);
// save actual arguments when fn called
const callArgRef = useRef(options.initArgs || []);
// save real callback function
const fnRef = useRef(fn);
// wrapped function
const trigger = useCallback(function () {
callArgRef.current = [].slice.call(arguments);
setNum((prev) => {
return prev + 1;
});
}, []);
// update real callback
useEffect(function () {
fnRef.current = fn;
});
useEffect(
function () {
if (num === INIT_VALUE && !options.imediate) {
// prevent init call
return;
}
return fnRef.current.apply(null, callArgRef.current);
},
[num, options.imediate]
);
return trigger;
}
@sophister
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment