A lightweight, production-ready React hook for making HTTP requests — with:
- ✅ Built-in GET request caching
- ✅ Waterfall protection for shared concurrent requests
- ✅ Native AbortController handling
- ✅ Optional debounce delay
- ✅ Easy refetch and manual cache invalidation
- ✅ Zero dependencies — just
fetchand idiomatic React
No more boilerplate, stale fetches, or duplicate network calls.
useHttpRequest is for React developers who want:
- Clean async logic without
useEffectgymnastics - Reliable loading/error/data state without manual tracking
- Built-in caching and request deduplication (waterfall protection)
- Auto-abort behavior to prevent memory leaks
- Full support for
GET,POST,PUT,DELETE, and custom configs
Perfect for:
- Fetching data on mount
- Debounced APIs (e.g., search/autocomplete)
- Avoiding redundant GET calls in multiple components
- Keeping UI state clean, responsive, and React-idiomatic
useHttpRequest() is a custom React hook that simplifies fetch() logic inside functional components.
It handles:
- What to fetch (
url) - How to fetch (method, headers, body)
- When to fetch (with debounce and cleanup)
- What to do with the result (
data,error,isLoading)
You use it like this:
const { data, error, isLoading, refetch } = useHttpRequest(url, options);npm install @mdus/use-http-request-hook
# or
yarn add @mdus/use-http-request-hook| Argument | Type | Required | Description |
|---|---|---|---|
url |
string |
✅ Yes | The URL or endpoint to fetch data from |
options |
object |
❌ No | An optional object to configure the request |
| Option | Type | Default | Description |
|---|---|---|---|
method |
string |
"GET" |
HTTP method ("GET", "POST", "PUT", "DELETE" etc.) |
headers |
object |
{} |
Any custom headers (Content-Type, auth tokens, etc.) |
body |
object |
null |
Payload for non-GET requests (automatically stringified) |
debounce |
number |
0 |
Delay in milliseconds before the request is sent |
| Key | Type | Description |
|---|---|---|
data |
any |
The JSON response from the API (or null initially) |
isLoading |
boolean |
true while request is in progress |
error |
string |
Error message if something goes wrong |
refetch |
function |
Manually re-trigger the request |
import useHttpRequest from "@mdus/use-http-request-hook";
function Products() {
const { data, isLoading, error } = useHttpRequest("https://fakestoreapi.com/products");
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{data?.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
}const { data, error, isLoading } = useHttpRequest("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: {
name: "Alice",
email: "alice@example.com"
}
});const { data, isLoading } = useHttpRequest(`https://api.com/search?q=${query}`, {
debounce: 500 // Waits 500ms after typing stops
});const { data, refetch } = useHttpRequest("https://api.com/stats");
<button onClick={refetch}>Refresh Data</button>- Only
GETrequests are cached by default - Cached in memory (not persisted to disk)
- Avoids repeat requests during a session
// Will use cache if already fetched:
useHttpRequest("https://api.com/items");Multiple components requesting the same GET URL won't duplicate the request:
// Component A
useHttpRequest("https://api.com/profile");
// Component B
useHttpRequest("https://api.com/profile");
// ✅ Only one fetch will actually run — both use same in-flight promiseimport { clearCache, invalidateURL } from "@mdus/use-http-request-hook";
clearCache(); // Wipe all cached GET responses
invalidateURL("https://api.com/products"); // Clear just one- You call
useHttpRequest(url, options) - The hook checks if this is a
GETrequest and already cached - If not cached, it creates a
fetch()request withAbortController - While the request is in progress,
isLoadingistrue - If successful,
datais filled and cached (forGETonly) - If there's an error, it shows up in
error - If component unmounts or URL changes, the request is safely aborted
- Cancels in-progress requests if:
- Component unmounts
- URL or
optionschange
- Prevents memory leaks or setting state on an unmounted component
- Uses native
fetch()withAbortControllerfor safety GETresponses cached in aMap(session memory)- In-flight GET requests tracked in another
Mapto prevent waterfall issues - Uses
setTimeoutfor debouncing and cleans up on unmount - React
useRef,useCallback, anduseMemoensure stability across renders
use-http-request-hook/
├── src/
│ └── useHttpRequest.js
├── dist/
│ └── index.js
├── package.json
└── README.md
Md Umar Siddique
- GitHub: @umarSiddique010
- LinkedIn: md-umar-siddique
- X / Twitter: @umarSiddique010
- Dev.to: @umarSiddique010
MIT © 2025 Md Umar Siddique
This hook is designed to solve real problems React developers face every day — while staying small, composable, and dependency-free. It's a reflection of production-level thinking: eliminating duplication, managing edge cases, and creating a smoother dev experience.
If it helps you, feel free to star, use, and share.