Skip to content

Instantly share code, notes, and snippets.

@jviall
Last active August 4, 2020 16:18
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 jviall/3c5c1bdfea34c2d7ea3d024b4a6f9c8b to your computer and use it in GitHub Desktop.
Save jviall/3c5c1bdfea34c2d7ea3d024b4a6f9c8b to your computer and use it in GitHub Desktop.
type-ified version of react-table's useAsyncDebounce hook
export function useAsyncDebounce<T extends (args: any[]) => any>(defaultFn: T, defaultWait: number): T {
const debounceRef = React.useRef<{
promise?: Promise<T>,
resolve?: (value: T | PromiseLike<T>) => void,
reject?: (reason?: any) => void,
timeout?: NodeJS.Timeout
}>({})
// the given args could be props, which change, so we want to always use latest definitions.
const getDefaultFn = useGetLatest(defaultFn)
const getDefaultWait = useGetLatest(defaultWait)
return React.useCallback(
((async (...args) => {
// make a promise
if (!debounceRef.current.promise) {
debounceRef.current.promise = new Promise((resolve, reject) => {
debounceRef.current.resolve = resolve
debounceRef.current.reject = reject
})
}
if (debounceRef.current.timeout) {
clearTimeout(debounceRef.current.timeout)
}
debounceRef.current.timeout = setTimeout(async () => {
// Executing a debounced call--don't let it be canceled.
delete debounceRef.current.timeout
try {
debounceRef.current.resolve(await getDefaultFn()(...args))
} catch (err) {
debounceRef.current.reject(err)
} finally {
delete debounceRef.current.promise
}
}, getDefaultWait())
return debounceRef.current.promise
}) as T),
[getDefaultFn, getDefaultWait]
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment