-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Write Custom useDebouncedCallback
Hook & Partially Remove Lodash Dependency
#788
base: master
Are you sure you want to change the base?
Changes from all commits
8470a36
09f774e
a89e573
42e99b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { useRef, useCallback } from 'react' | ||
|
||
/** | ||
* Returns a memoized function that will only call the passed function when it hasn't been called for the wait period | ||
* @param callback The function to be called | ||
* @param wait Wait period after function hasn't been called for | ||
* @returns A memoized function that is debounced | ||
*/ | ||
const useDebouncedCallback = <CallbackArgs extends any[]>( | ||
callback: (...args: CallbackArgs) => void, | ||
wait: number, | ||
) => { | ||
// Use a ref to store the timeout between renders | ||
// and prevent changes to it from causing re-renders | ||
const timeout = useRef() | ||
|
||
return useCallback( | ||
(...args) => { | ||
const later = () => { | ||
clearTimeout(timeout.current) | ||
callback(...args) | ||
} | ||
|
||
clearTimeout(timeout.current) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the behavior that's implemented here is that any call to the debounced function will wait at least This is apparently lodash's definition of "debounce", but I think the behavior we actually want is what lodash calls "throttle", meaning the function will be invoked at most once in a period of So the logic for that would be something like:
This is based on the assumption that in the scrolling case, we do want to continue to call this function while scroll events are happening and continue updating the toolbar position, not wait until all the scrolling action has stopped, we just want to limit the frequency at which that happens |
||
timeout.current = setTimeout(later, wait) | ||
}, | ||
[callback, wait], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because Since callers will have to memoize anyway (and the |
||
) | ||
} | ||
|
||
export default useDebouncedCallback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling a hook inside a
useEffect
callback is invalid, which contributes to the case for this being a simple function rather than a hook.