DEV Community

Cover image for ๐Ÿš€ Smarter Debouncing in React โ€” Introducing `@er-raj-aryan/use-smart-debounce`
Raj Aryan
Raj Aryan

Posted on

๐Ÿš€ Smarter Debouncing in React โ€” Introducing `@er-raj-aryan/use-smart-debounce`

Tired of making a dozen API calls every time a user types three letters?
Meet @er-raj-aryan/use-smart-debounce โ€” a lightweight React hook library that makes debouncing async-safe, TypeScript-ready, and smooth like butter ๐Ÿงˆ

๐Ÿ‘‰ NPM: @er-raj-aryan/use-smart-debounce
๐Ÿ‘‰ GitHub: https://github.com/er-raj-aryan/use-smart-debounce


๐Ÿ’ก Why I Built This

While building a Next.js dashboard, I ran into the same old issue โ€” API calls firing on every keystroke during search input.
Existing solutions like lodash.debounce or use-debounce didnโ€™t handle async calls, cancellation, or stale responses well.

So I decided to build something that does:

  • Cancels stale API requests
  • Handles async promises safely
  • Works with leading, trailing, and maxWait modes
  • Comes with full TypeScript support
  • Ships with zero dependencies

โš™๏ธ Installation

npm i @er-raj-aryan/use-smart-debounce # or yarn add @er-raj-aryan/use-smart-debounce 
Enter fullscreen mode Exit fullscreen mode

๐Ÿงฉ Whatโ€™s Inside

Hook Use Case Description
useDebouncedValue Debounce values Returns a delayed version of any state value
useDebouncedCallback Debounce functions Debounce any callback with leading/trailing control
useDebouncedAsync Debounce async calls Cancels in-flight requests & ignores stale responses

๐Ÿง  Basic Example โ€” Debounce a Value

import { useDebouncedValue } from "@er-raj-aryan/use-smart-debounce"; import { useState, useEffect } from "react"; export default function SearchBox() { const [query, setQuery] = useState(""); const debouncedQuery = useDebouncedValue(query, 500); useEffect(() => { if (debouncedQuery.length >= 3) { console.log("Search:", debouncedQuery); } }, [debouncedQuery]); return ( <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Type to searchโ€ฆ" /> ); } 
Enter fullscreen mode Exit fullscreen mode

โœ… Fires only after 500ms of inactivity
โœ… Perfect for live search or filtering


โšก Debounce Callbacks with Control

import { useDebouncedCallback } from "@er-raj-aryan/use-smart-debounce"; function ResizeTracker() { const debouncedResize = useDebouncedCallback( () => console.log("Window resized:", window.innerWidth), 300, { leading: false, trailing: true } ); useEffect(() => { window.addEventListener("resize", debouncedResize); return () => window.removeEventListener("resize", debouncedResize); }, []); return <p>Resize the window to see it in action</p>; } 
Enter fullscreen mode Exit fullscreen mode

๐Ÿช„ Async-Safe Debouncing

This is where most debounce hooks fail โ€” multiple async calls return out of order, and the old response overwrites the new one.
useDebouncedAsync handles that for you:

import { useDebouncedAsync } from "@er-raj-aryan/use-smart-debounce"; import { useState, useEffect } from "react"; function LiveSearch() { const [query, setQuery] = useState(""); const { run, status, data, error } = useDebouncedAsync( async (q: string) => { if (q.length < 3) return []; const res = await fetch(`/api/search?q=${encodeURIComponent(q)}`); const json = await res.json(); return json.results ?? []; }, 500 ); useEffect(() => { run(query); }, [query]); return ( <div> <input value={query} onChange={(e) => setQuery(e.target.value)} /> {status === "loading" && <p>Loadingโ€ฆ</p>} {error && <p style={{ color: "red" }}>Error fetching</p>} <ul> {Array.isArray(data) && data.map((r: any) => <li key={r.id}>{r.name}</li>)} </ul> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

โœจ Features:

  • Cancels the previous API call when user keeps typing
  • Prevents stale results from overwriting fresh ones
  • Tracks status, data, and error

๐Ÿงฎ Real Example โ€” HS Code Lookup with Material UI

Hereโ€™s a practical example using MUIโ€™s <Autocomplete> with your HS Code API (/db/hs_code_list/?search_key=):

import { Autocomplete, TextField } from "@mui/material"; import { useDebouncedAsync } from "@er-raj-aryan/use-smart-debounce"; import { useState, useEffect } from "react"; type HS = { hs_code: string; description: string }; export default function HSCodeSearch() { const [value, setValue] = useState<HS | null>(null); const [options, setOptions] = useState<HS[]>([]); const { run, status, data } = useDebouncedAsync( async (q: string) => { if (q.length < 3 || !/^\d+$/.test(q)) return []; const res = await fetch(`/db/hs_code_list/?search_key=${q}`); const json = await res.json(); return json.results ?? []; }, 600 ); useEffect(() => { if (Array.isArray(data)) setOptions(data); }, [data]); return ( <Autocomplete size="small" options={options} value={value} onChange={(_, v) => setValue(v)} getOptionLabel={(o) => o.hs_code} onInputChange={(_, v) => run(v)} renderInput={(params) => ( <TextField {...params} label="HS Code" helperText={ value?.description || (status === "loading" ? "Searching..." : "") } /> )} /> ); } 
Enter fullscreen mode Exit fullscreen mode

โš–๏ธ Comparison Table

Feature @er-raj-aryan/use-smart-debounce use-debounce ahooks lodash.debounce
๐Ÿง  TypeScript support โœ… Native โœ… โœ… โŒ
โš™๏ธ Async-safe โœ… Cancels + ignores stale โŒ โš ๏ธ Partial โŒ
๐Ÿ” Leading/Trailing โœ… โš ๏ธ Partial โœ… โœ…
๐ŸŒ€ Race protection โœ… Yes โŒ โŒ โŒ
โšก Bundle size <3 KB ~4 KB ~200 KB 24 KB
๐Ÿงฉ Dependencies 0 0 20+ 1
๐Ÿงฐ Designed for React โœ… Hooks โœ… Hooks โœ… โŒ

๐Ÿš€ Why Youโ€™ll Love It

  • No dependencies โ†’ ultra-fast build
  • Tiny footprint โ†’ great for production apps
  • Async-safe โ†’ ideal for API-driven UIs
  • TypeScript-ready โ†’ works out of the box

๐Ÿ Wrap Up

If youโ€™re building React apps that rely on API queries, form inputs, or live filters โ€”
@er-raj-aryan/use-smart-debounce will save you time, requests, and user frustration.

๐Ÿ‘‰ Install now:

npm i @er-raj-aryan/use-smart-debounce 
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”— Links:


๐Ÿง‘โ€๐Ÿ’ป Author: Er Raj Aryan
Frontend Engineer | React / Next.js Developer | Open Source Enthusiast

If you found this useful โ€” โญ๏ธ the repo or drop a comment!
Letโ€™s build smarter UIs together ๐Ÿ’™

Top comments (0)