useHttpRequest
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
fetch
and idiomatic React
Why Use This Hook?
No more boilerplate, stale fetches, or duplicate network calls.
useHttpRequest
is for React developers who want:
- Clean async logic without
useEffect
gymnastics - 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
What Is This?
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);
Installation
npm install @mdus/use-http-request-hook
# or
yarn add @mdus/use-http-request-hook
API Reference
What It Expects
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 |
What Goes Inside options
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 |
What It Returns
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 |
Examples
1. Simple GET 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>
);
}
2. POST Request with JSON Body
const { data, error, isLoading } = useHttpRequest("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: {
name: "Alice",
email: "alice@example.com"
}
});
3. Debounced GET Request (e.g., Search Input)
const { data, isLoading } = useHttpRequest(`https://api.com/search?q=${query}`, {
debounce: 500 // Waits 500ms after typing stops
});
4. Manual Refetch
const { data, refetch } = useHttpRequest("https://api.com/stats");
<button onClick={refetch}>Refresh Data</button>
Advanced Features
GET Caching
- Only
GET
requests 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");
Waterfall Protection
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 promise
Manual Cache Control
import { clearCache, invalidateURL } from "@mdus/use-http-request-hook";
clearCache(); // Wipe all cached GET responses
invalidateURL("https://api.com/products"); // Clear just one
How It Works (Beginner-Friendly Flow)
- You call
useHttpRequest(url, options)
- The hook checks if this is a
GET
request and already cached - If not cached, it creates a
fetch()
request withAbortController
- While the request is in progress,
isLoading
istrue
- If successful,
data
is filled and cached (forGET
only) - If there's an error, it shows up in
error
- If component unmounts or URL changes, the request is safely aborted
Auto Cleanup
- Cancels in-progress requests if:
- Component unmounts
- URL or
options
change
- Prevents memory leaks or setting state on an unmounted component
How It Works Internally
- Uses native
fetch()
withAbortController
for safety GET
responses cached in aMap
(session memory)- In-flight GET requests tracked in another
Map
to prevent waterfall issues - Uses
setTimeout
for debouncing and cleans up on unmount - React
useRef
,useCallback
, anduseMemo
ensure stability across renders
File Structure
use-http-request-hook/
├── src/
│ └── useHttpRequest.js
├── dist/
│ └── index.js
├── package.json
└── README.md
Author
Md Umar Siddique
- GitHub: @umarSiddique010
- LinkedIn: md-umar-siddique
- X / Twitter: @umarSiddique010
- Dev.to: @umarSiddique010
License
MIT © 2025 Md Umar Siddique
Final Note
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.