Debounce vs useDebounce in React

useDebounce vs debounce() I got this wrong for months. Working on user forms and search where, every keystroke was triggering an API call. I reached for debounce() first. Big mistake. Here’s what I learned: Wrong - debounce() in render body // Re-creates a new debounced fn on EVERY render const handleSearch = debounce((val) => fetchResults(val), 300); Better - but needs careful handling // Stable across renders, but you manage the fn ref const handleSearch = useRef( debounce((val) => fetchResults(val), 300) ).current; Cleanest - useDebounce hook const [query, setQuery] = useState(''); const debouncedQuery = useDebounce(query, 300); useEffect(() => { if (debouncedQuery) fetchResults(debouncedQuery); }, [debouncedQuery]); // fires only after user stops typing The core difference: debounce(fn) → delays a function call. Lives outside React. Needs useRef to stay stable. useDebounce(value) → delays a state value. React-native, auto-cleanup via useEffect. No ref juggling. My rule now: → Input-driven API calls? useDebounce → Click/scroll/resize handlers? debounce() inside useRef This one pattern alone cut our unnecessary API calls by ~80% on the search feature. What’s your go-to approach? Drop it below 👇 #React #ReactHooks #FrontendEngineering #JavaScript #WebPerformance #ReactDeepDive #SeniorEngineer

To view or add a comment, sign in

Explore content categories