Today I'm going to show you how to build a useDebounce React Hook that makes it super easy to debounce API calls to ensure that they don't execute ...
For further actions, you may consider blocking this person and/or reporting abuse
Why not just:
Now you can use this debouce in other hooks.
how do you make the call debounce function ?
nope not working , geting the state value as undefined
Are you able to show your code for the event handler and how you trigger the call?
i have triggered the call in the same way, but it is not working at all ,and state is undefined
My aproach is this way:
This looks great! Could you give us an example on how to implement it?
whilst I like the idea of this, I think the UI and the API call should be far more decoupled, so instead I've went for:
Great article!
I've been using this pattern with hooks lately:
It's clean and works well for most of the cases.
Here's a version
useDebounce
implemented using lodash: github.com/gnbaron/use-lodash-debo...Here’s my take on a
lodash.debounce
hook. I don’t see why the hook shouldn’t be more convenient to use, so I basically made auseState
wrapper which updates the value immediately (a requirement for controlled inputs), and updates asignal
, which is meant to be used in auseEffect
’s dependency array, only whenever specified as perlodash.debounce
’s docs.Great - thanks! The example would be easier to read if you included all the imports and exports. Great job.
Good call! Just updated the post.
Awesome! :)
why dont we do this in the useEffect?
i tried this but the cleartimeout was not working, the timeout was not being cleared, i didnt understand the reason.
can anyone explain?
Thanks for share!
Very helpful, thank you! Years ago I needed something like this and ended up using throttle feature of redux sagas. Not bad, but I try to avoid redux (gets a bit unreadable over time).
I'm writing a new app and needed an "auto-save" feature where a form is auto-saved every x seconds, provided any of the inputs were changed. I started doing my own thing (setTimeout, setInterval) and luckily stumbled on this post. Saved me time. Elegant and it works.
Throttling API calls from UI is a very important technique to learn, I wish Facebook would throw some sort of "autocomplete" or "lookup text field" example where they use your code.
This makes the most since:
import { useCallback, useRef } from 'react'
export default function useDebounce(func, delay = 400) {
let debounce = useRef(null)
return useCallback(
(...args) => {
const context = this
clearTimeout(debounce.current)
debounce.current = setTimeout(() => {
func.apply(context, args)
}, delay)
},
[func],
)
}
Usage:
const handleWindowResize = useDebounce(SetWindow)
useEffect(() => {
window.addEventListener('resize', handleResize)
}, [])
Hmm this doesn't seem to work if you add text after the initial query (i.e. 'wolverine' as the first full term to debounce, then appending it to become 'wolverine x-men'.. the 'x-men' part doesnt show up until the debouncing times out). I feel like this code is so short and simple I should be able to figure it out, but I can't seem to see why the UI lags so hard on the second set of characters.
Aha, I take it back! Turns out I needed to pull my search input into its own component. Problem solved! (I think)
How could you modify this to make it a "leading" debounce?
Awesome! I had a similar project and this looked easier than I thought!
Why using
useEffect
for the api call? I don't see any issue with doing async api calls inside a component rendering function.Any side effects should be wrapped in useEffect or within an event handler like onClick. Not sure what could go wrong by inlining it like that, but know it’s heavily discouraged by the React team.
You wrap side effects in useEffect so they don't run on every render. You technically could make a request inside render without wrapping it in useEffect, but it'll happen on every single render, which is usually not what you want.
You typically only want side effects to run when things they care about change, like when some search text changes. That's exactly what useEffect does for you - it helps make sure the side effects only run when they need to.
This reply is great, thanks!
Loved the explanation. Thanks!
Although I would use useRef hook to set the timer variable to reduce the heap memory usage.
Hi,
Thanks for the article. I'm curious about the chosen approch of providing a value to the custom hook that gets updates over time.
Here we listen to
value
changes in the custom hook with the inneruseEffect
and react to changes. Most of the hooks I'm familiar with treat the arguments they get as sort of initialization values that doesn't change overtime or even if changed are not monitored. For exampleuseState, useReducer, useSelector, useMemo, useCallback, useRef
are all hooks that doesn't react to changes of the initial values provided to the hook.I know that your sample works and is valid implementation but I'm sure if it will not confuse developers who read the code. you could easily expose a second argument to update the value which will look very similar to
useState
wdyt?
useCallback
,useSelector
,useMemo
,useReducer
are actually operating on most recent arguments each run.It's only
useState
anduseRef
who purposely ignore any changes on sequential callsAmazing, did not think to have
debouncedValue
instead of debounced version of callback.Probably we better cancel processing in main
useEffect
to avoid race conditions.This was a great guide, had been struggling for a while with getting something like this to work.
Thanks!
Thanks! Helped me a lot
You've got a missing
=
hereThis is really elegant! Have you thought about publishing this as a node_module?
Great read!
Just as a side note: you don't have to import react to your use-debounce.js.
" import { useState, useEffect } from 'react';"is just fine
Excellent!
Needed this and was struggling a bit myself to get it to work flawlessly...
Thanks!
this is not working, i am getting redundant calls, the function calls are not getting cancelled
Great work, thanks a lot. I want to write a similar post in my native language Bangla, is this ok if i use your post as reference and also your demo project to show how this work ?
Yeah sure! Please just link to my post as well somewhere.
Thank you so much, i will.
thank you, kind sir!
Try to hold down any key and you will see, that searching appears 2 times - after 500 ms after the first character and after 500 ms after the last. How to avoid this glitch?
Very useful. I signed up only to thank you.
Very nice code! :) very helpfull
Thank you for sharing that, it's a very useful and simple way.
This was incredibly helpful in figuring out how to debounce with my custom hook fetch. Thank you!