I could have use the Loadash naaahh... 🙅♀️ Loadash is too expensive.
So here is how you can make your own debounce effect with custom hooks in react js.
updated as per @lukeshiru comment
useDebouncedEffect.tsx
import { DependencyList, EffectCallback, useEffect } from "react";
export const useDebouncedEffect = (
effect: EffectCallback,
delay: number,
deps?: DependencyList
) => {
useEffect(() => {
const handler = setTimeout(() => effect(), delay);
return () => clearTimeout(handler);
// using || operator because
// if its optional then it can be undefined.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [...(deps || []), delay]);
};
To use this hook simply call It like this:
import { useDebouncedEffect } from "./useDebouncedEffect";
// debounce search onchange
// eslint-disable-next-line react-hooks/exhaustive-deps
useDebouncedEffect(
() => {
// function which will be running on effect,
// in our case when something changes in search box.
changeSearchState();
},
// time to wait before effect runs
debounceTimeInMilliseconds
// this is the dependency, if it changes it will trigger
// the debounce again
[search]
);
credit - from Internet [R&D]
Thanks for reading this far 😃
Fact: Do you know you can hit that follow button on top right and make it disappear 😄. Do not believe me try once 👍
Top comments (5)
Using TypeScript, you should avoid
any
as much as possible, so a fixed version would look more like this:About the actual implementation, this wouldn’t produce a great DX mainly because we need to pass a dependency list even if we want to runt it "always", so
deps
ideally should be optional as it is foruseEffect
, but then we have the problem that you putdelay
as the last argument, and that one is required. Ideally the argument order should change like this:And you could even make it into a curried function and keep it pretty similar to a regular hook:
And then you use it like this:
Still, my recommendation would be to use a library for this, like the pretty good use-debounce.
Cheers!
Not useful in this case, yes we can suppress TS warning but It will not be a good idea.
The linter doesn't know how are you using your code so it gives you those warnings, if you use it as I said (first call of the curried version outside the component, second inside) it works exactly the same as a regular hook. Linters are there to help, but they aren't silver bullets, you have to understand the reason for the warnings and errors you get.
Didn't tried the
use-debounce
but theloadsh's
Debounce was having some state persistence issue.Your comment is super helpful, thanks man 🤘
export function useDebouncedValue(value, wait) {
const [debouncedValue, setDebouncedValue] = useState(value);
return debouncedValue;
}