Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
YouTube Security VideosNutanix advances legacy and AI app management with AMD(01.10.2026 um 16:00 Uhr)
•
YouTube Security VideosPC-WELT: 32 TB SSD-Speicher in der HMX 6!(01.10.2026 um 16:15 Uhr)
••••
Videos & KonferenzenPC-WELT: 32 TB SSD-Speicher in der HMX 6!(01.10.2026 um 16:15 Uhr)
••
Sicherheitslücken (CVE)USN-8857-1: KCoreAddons vulnerability(01.10.2026 um 12:48 Uhr)
•••
YouTube Security VideosNutanix advances legacy and AI app management with AMD(01.10.2026 um 16:00 Uhr)
•
YouTube Security VideosPC-WELT: 32 TB SSD-Speicher in der HMX 6!(01.10.2026 um 16:15 Uhr)
••••
Videos & KonferenzenPC-WELT: 32 TB SSD-Speicher in der HMX 6!(01.10.2026 um 16:15 Uhr)
••
Sicherheitslücken (CVE)USN-8857-1: KCoreAddons vulnerability(01.10.2026 um 12:48 Uhr)
•••
Intelligence View
⚡ tsecurity.de Intelligence

I Built a Production-Ready useFetch Hook with TypeScript — Here's What I Learned (Full Source Code)

🎣 The Hook The first 3 lines decide if someone stays . "I wasted months rewriting the same fetch logic in every React project. One weekend, I built a hook that …

Beitrag
0
Seite
0
↗ Quelle (dev.to)
Social ReaktionenReagiere als Erste:r — dein Feedback zählt!

🎣 The Hook



The first 3 lines decide if someone stays .

"I wasted months rewriting the same fetch logic in every React project. One weekend, I built a hook that eliminated 100% of that boilerplate. Here it is, free and open-source."



You know the drill. You start a new React component, and before you write a single line of UI, you're already typing:

const [data, setData] = useState(null);

const [loading, setLoading] = useState(false);

const [error, setError] = useState(null);

useEffect(() => { ...



It's tedious. It clutters your components. And if you forget to clean up with an AbortController? You've got memory leaks and that dreaded "Can't perform a React state update on an unmounted component" warning.



I finally got tired of it and built useFetch : a single, production-ready custom hook that handles fetching, caching, loading states, and request cancellation with full TypeScript support.



Today, I'm giving you the full source code and explaining the key design decisions that make it "production-ready."



Why Not Just Use React Query or SWR?

This is the first question I get. Libraries like React Query and SWR are fantastic, but they are heavy.



Zero Dependencies: My hook is under 3KB. It doesn't bring an entire state management layer into your bundle.



Full Control: You own the code. It's a single file you can drop into your src/hooks folder and customize to your heart's content.



Learning Experience: Understanding how these hooks work under the hood makes you a better engineer.



🚀 The Code: A Step-by-Step Breakdown

Let's build this. We need it to be type-safe, handle race conditions, and include a smart caching layer.




  1. TypeScript First: Defining the Contract
    Always start with the types. This makes the actual implementation trivial.



typescript

interface UseFetchOptions {

initialData?: T | null;

cacheDuration?: number; // Cache time in ms

skip?: boolean; // Don't fetch automatically

onSuccess?: (data: T) => void;

onError?: (error: Error) => void;

deps?: unknown[]; // Re-fetch dependencies

}



interface UseFetchReturn {

data: T | null;

loading: boolean;

error: Error | null;

refetch: () => Promise;

clearCache: () => void;

}




  1. The Singleton Cache (The Secret Sauce)
    To avoid fetching the same user profile 50 times across different components, we need a global cache. We use a simple JavaScript object with a TTL (Time To Live) to ensure data freshness.



typescript

// cacheManager.ts

const cache = new Map();



export const cacheManager = {

get(key: string, ttl: number): T | null {

const entry = cache.get(key);

if (!entry) return null;

if (Date.now() - entry.timestamp > ttl) {

cache.delete(key);

return null;

}

return entry.data as T;

},

set(key: string, data: unknown): void {

cache.set(key, { data, timestamp: Date.now() });

},

clear(key: string): void {

cache.delete(key);

}

};




  1. The Hook Implementation: Taming Race Conditions
    The critical part is the AbortController. Without it, if a user clicks "User 1" then quickly clicks "User 2", a slow API response for User 1 might arrive after User 2's data, overriding the state with stale information .



tsx

import { useEffect, useState, useCallback, useRef } from 'react';



export function useFetch(

url: string | null,

options: UseFetchOptions = {}

): UseFetchReturn {

const { cacheDuration = 300000, skip = false, deps = [] } = options;

const [data, setData] = useState(options.initialData || null);

const [loading, setLoading] = useState(!skip);

const [error, setError] = useState(null);

const abortControllerRef = useRef(null);



const fetchData = useCallback(async () => {

if (!url) return;




// 1. Check Cache
const cached = cacheManager.get<T>(url, cacheDuration);
if (cached) {
setData(cached);
setLoading(false);
return;
}

// 2. Cancel previous call
abortControllerRef.current?.abort();
abortControllerRef.current = new AbortController();

try {
setLoading(true);
const response = await fetch(url, { signal: abortControllerRef.current.signal });
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

const result = await response.json();
cacheManager.set(url, result);
setData(result);
options.onSuccess?.(result);
} catch (err) {
// Ignore abort errors - they are intentional
if (err instanceof Error && err.name !== 'AbortError') {
setError(err);
options.onError?.(err);
}
} finally {
setLoading(false);
}




}, [url, cacheDuration]);



useEffect(() => {

if (skip) return;

fetchData();

// Cleanup: Abort request on unmount

return () => abortControllerRef.current?.abort();

}, [fetchData, skip, ...deps]);



const refetch = useCallback(() => {

cacheManager.clear(url!);

fetchData();

}, [fetchData, url]);



return { data, loading, error, refetch, clearCache: () => cacheManager.clear(url!) };

}

🛠️ How to Use It (It's Stupidly Simple)

Using the hook is cleaner than your current useEffect soup.



tsx

interface User {

id: number;

name: string;

}



const UserProfile = ({ userId }: { userId: number }) => {

const { data: user, loading, error } = useFetch(

https://api.example.com/users/${userId},

{ deps: [userId] } // Auto re-fetch when userId changes

);



if (loading) return ;

if (error) return ;



return

Welcome back, {user?.name}!;

};

🏆 Why This Will Save You Hours

No More Memory Leaks: The AbortController cleanup ensures you never update an unmounted component.

Instant Back-Navigation: Caching means data appears instantly when revisiting a page. No loading spinners.



Type Safety: Generics ensure data is fully typed as User or Product[]. No more any.



📦 Full Production-Ready Code

I've prepared a complete, split-source GitHub repository with:



✅ Full TypeScript support



✅ Comprehensive Unit Tests



✅ Advanced Caching with TTL



✅ GitHub Actions CI/CD setup



✅ A beautiful README ready for npm



👉 GitHub Repo: use-fetch-cache

Don't forget to drop a ⭐ if you find it useful!



💬 Final Thoughts

Building your own tools is the best way to master a framework. You don't always need a 20kB third-party library to solve a 2kB problem. By writing useFetch, you've taken control of your data layer and reduced your bundle size simultaneously.



Have you built a custom hook that changed your workflow? Drop a comment below—I'd love to see what you're building!

🔍 CTI & Forensik

Cyber Threat Intelligence & Forensik

Bedrohungsgraph · ATT&CK-Mapping · Exploit-Belege
CTI Threat Relationship Graph
Akteure · Techniken · Beziehungen
2 Knoten · 1 Relationen
CVE / Incident Threat Actor Software MITRE ATT&CK CWE Weakness IoC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten I Built a Production-Ready useFetch Hook with TypeScript — Here's What I Learned (Full Source Code)

Thematisch verwandte Begriffe: Built, ProductionReady, useFetch, Hook · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag