Skip to content

Instantly share code, notes, and snippets.

@mudge
Last active September 22, 2022 10:14
Show Gist options
  • Save mudge/eb9178a4b6d595ffde8f9cb31744afcf to your computer and use it in GitHub Desktop.
Save mudge/eb9178a4b6d595ffde8f9cb31744afcf to your computer and use it in GitHub Desktop.
A custom React Hook for a debounced click handler with a given callback and delay.
/*
* Inspired by Dan Abramov's "Making setInterval Declarative with React Hooks",
* this is a custom hook for debouncing a callback (e.g. for click handlers) such
* that a callback will not be fired until some delay has passed since the last click.
* The callback will automatically be updated with the latest props and state on every
* render meaning that users don't need to worry about stale information being used.
*
* See https://overreacted.io/making-setinterval-declarative-with-react-hooks/ for the
* original inspiration.
*/
import React, { useState, useEffect, useRef } from 'react';
const useDebounce = (callback, delay) => {
const latestCallback = useRef();
const latestTimeout = useRef();
useEffect(() => {
latestCallback.current = callback;
}, [callback]);
return () => {
if (latestTimeout.current) {
clearTimeout(latestTimeout.current);
}
latestTimeout.current = setTimeout(() => { latestCallback.current(); }, delay);
};
};
const App = () => {
const [count, setCount] = useState(0);
const handleIncrement = () => setCount(count => count + 1);
const handleClick = useDebounce(() => alert(`I've been clicked ${count} times`), 3000);
return (
<>
<button onClick={handleClick}>Click</button>
<button onClick={handleIncrement}>Increment {count}</button>
</>
);
}
export default App;
@mudge
Copy link
Author

mudge commented Aug 26, 2019

Phew, thanks for putting my mind at ease on both points.

@vivekmittal
Copy link

How do I stop the propagation when the handler is an onSubmit function on form?

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