Last active
August 25, 2020 10:39
-
-
Save sophister/9cc74bb7f0509bdd6e763edbbd21ba64 to your computer and use it in GitHub Desktop.
React Hooks for debounce, useDebounce, useDebounceState, with cleanup surpport
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Live demo here: https://codesandbox.io/s/react-hook-debounce-demo-mgr89?file=/src/App.js