typescriptadvanced
Suspense Data Fetching Pattern
Use React Suspense for data fetching with resource caching, error boundaries, and streaming SSR.
typescriptPress ⌘/Ctrl + Shift + C to copy
import { Suspense } from 'react';
type Status = 'pending' | 'success' | 'error';
interface Resource<T> {
read(): T;
}
function createResource<T>(promise: Promise<T>): Resource<T> {
let status: Status = 'pending';
let result: T;
let error: Error;
const suspender = promise.then(
(data) => { status = 'success'; result = data; },
(err) => { status = 'error'; error = err; },
);
return {
read() {
switch (status) {
case 'pending': throw suspender;
case 'error': throw error;
case 'success': return result;
}
},
};
}
// Cache factory
function createResourceCache<T>() {
const cache = new Map<string, Resource<T>>();
return {
get(key: string, fetcher: () => Promise<T>): Resource<T> {
if (!cache.has(key)) {
cache.set(key, createResource(fetcher()));
}
return cache.get(key)!;
},
invalidate(key: string) { cache.delete(key); },
clear() { cache.clear(); },
};
}
// Usage
interface User { id: string; name: string; avatar: string }
const userCache = createResourceCache<User>();
function UserCard({ userId }: { userId: string }) {
const resource = userCache.get(userId, () =>
fetch(`/api/users/${userId}`).then(r => r.json()),
);
const user = resource.read(); // Suspends if pending, throws if error
return (
<div className="bg-[#111] border border-white/10 rounded-xl p-4 flex items-center gap-3">
<img src={user.avatar} alt="" className="w-10 h-10 rounded-full" />
<div>
<p className="text-white font-medium">{user.name}</p>
<p className="text-gray-400 text-sm">{user.id}</p>
</div>
</div>
);
}
function App() {
return (
<Suspense fallback={<div className="animate-pulse bg-gray-800 h-20 rounded-xl" />}>
<UserCard userId="user-1" />
</Suspense>
);
}
export { createResource, createResourceCache };Use Cases
- Suspense-first data loading
- Streaming SSR data patterns
- Resource caching layer
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptintermediate
React Custom Hook for Data Fetching
A reusable useFetch hook with loading states, error handling, caching, and abort support.
Best for: Reusable data fetching across components
#react#hooks
typescriptadvanced
React Compound Component Pattern
Build flexible compound components using React context for shared state between related parts.
Best for: Building flexible component libraries
#react#patterns
typescriptintermediate
React useReducer for Complex State
Manage complex component state with useReducer pattern including typed actions and middleware.
Best for: Shopping cart state management
#react#useReducer
typescriptintermediate
useAsync Hook for Promise Management
Manage async operations with loading, error, and data states using a reusable hook pattern.
Best for: Data fetching with status tracking
#react#hooks