Lightweight React hook for caching, prefetching, and refetching data with stale-time control.
npm install react-data-cacheA lightweight, performant React library for data fetching with built-in caching, prefetching, infinite scroll, and advanced features. Designed for modern React applications with TypeScript support.
- โก Zero Configuration - Works out of the box with sensible defaults
- ๐พ Automatic Caching - Data is cached and shared across components
- ๐ Smart Refetching - Intelligent stale-time based refetching
- ๐ฑ Infinite Scroll - Universal pagination support for any API
- ๐ฏ Prefetching - Proactive data loading for better UX
- ๐ Type Safety - Full TypeScript support with automatic type inference
- โก Performance - Efficient re-renders and request cancellation
- ๐ Universal - Works with any API structure and pagination pattern
#### High Priority Enhancements
- ๐ฏ Optimistic Updates - Instant UI updates with automatic rollback
- ๐ Advanced Retry Logic - Exponential backoff with custom error handling
- ๐ฑ Background Sync - Offline support with automatic synchronization
#### Medium Priority Enhancements
- ๐ Real-time Subscriptions - WebSocket integration for live updates
- ๐พ Advanced Caching - Multiple cache strategies (stale-while-revalidate, cache-first, etc.)
- ๐ Performance Monitoring - Built-in metrics and analytics
``bash`
npm install react-data-cacheor
yarn add react-data-cache
`typescript
import { useData } from 'react-data-cache';
function UserProfile({ userId }: { userId: string }) {
const { data, isLoading, error, refetch } = useData(
user-${userId},/api/users/${userId}
async (signal) => {
const response = await fetch(, { signal });
return response.json();
}
);
if (isLoading) return
{data.email}
๐ Enhanced Usage Examples
$3
`typescript
function OptimisticPostUpdate({ postId }: { postId: string }) {
const { data, updateOptimistically } = useData(
post-${postId},
async (signal) => {
const response = await fetch(/api/posts/${postId}, { signal });
return response.json();
},
{ optimisticUpdates: true }
); const handleLike = () => {
updateOptimistically(
{ likes: (data?.likes || 0) + 1 },
async () => {
await fetch(
/api/posts/${postId}/like, { method: 'POST' });
}
);
}; return (
{data?.title}
);
}
`$3
`typescript
function RobustDataFetch({ userId }: { userId: string }) {
const { data, error, retry, retryCount, metrics } = useData(
user-${userId},
async (signal) => {
const response = await fetch(/api/users/${userId}, { signal });
if (!response.ok) throw new Error(HTTP ${response.status});
return response.json();
},
{
retryAttempts: 5,
retryDelay: 1000,
exponentialBackoff: true,
onError: (error, attempt) => {
console.log(Attempt ${attempt} failed:, error.message);
},
enableMetrics: true
}
); if (error) {
return (
Failed to load user (attempt {retryCount})
Fetch time: {metrics.fetchTime}ms
);
} return ;
}
`$3
`typescript
function OfflineAwarePosts() {
const { data, syncStatus, metrics } = useData(
'posts',
async (signal) => {
const response = await fetch('/api/posts', { signal });
return response.json();
},
{
backgroundSync: true,
offlineSupport: true,
staleTime: 30 * 1000
}
); return (
Status: {syncStatus}
{data?.map(post => )}
);
}
`$3
`typescript
function LiveChat({ chatId }: { chatId: string }) {
const { data, isConnected } = useData(
chat-${chatId},
async (signal) => {
const response = await fetch(/api/chats/${chatId}/messages, { signal });
return response.json();
},
{
realtime: true,
subscriptionUrl: ws://api.example.com/chats/${chatId},
onUpdate: (newData) => {
console.log('New message received:', newData);
}
}
); return (
{isConnected ? '๐ข Connected' : '๐ด Disconnected'}
{data?.map(message => )}
);
}
`$3
`typescript
function SmartUserProfile({ userId }: { userId: string }) {
const { data, metrics } = useData(
user-${userId},
async (signal) => {
const response = await fetch(/api/users/${userId}, { signal });
return response.json();
},
{
cacheStrategy: "stale-while-revalidate",
cacheTime: 10 60 1000, // 10 minutes
backgroundRefetch: true,
enableMetrics: true
}
); return (
Cache hit rate: {(metrics.cacheHitRate * 100).toFixed(1)}%
);
}
`$3
`typescript
function MonitoredDataFetch() {
const { data, metrics } = useData(
'monitored-posts',
async (signal) => {
const response = await fetch('/api/posts', { signal });
return response.json();
},
{
enableMetrics: true,
onMetrics: (metrics) => {
// Send to analytics service
analytics.track('data_fetch_metrics', metrics);
}
}
); return (
Fetch Time: {metrics.fetchTime}ms
Cache Hit Rate: {(metrics.cacheHitRate * 100).toFixed(1)}%
{data?.map(post => )}
);
}
`๐ Documentation
- User Documentation - Complete guide for using the library
- Developer Documentation - Architecture and implementation details
๐ง Core API
$3
Main data fetching hook with caching and enhancements.
`typescript
const {
data,
isLoading,
error,
refetch,
// High Priority Enhancements
updateOptimistically,
retry,
retryCount,
syncStatus,
// Medium Priority Enhancements
isConnected,
metrics
} = useData(
'posts',
async (signal) => {
const response = await fetch('/api/posts', { signal });
return response.json();
},
{
// Standard options
staleTime: 5 60 1000,
refetchOnMount: true,
// High Priority Enhancements
optimisticUpdates: true,
retryAttempts: 5,
retryDelay: 1000,
exponentialBackoff: true,
backgroundSync: true,
offlineSupport: true,
// Medium Priority Enhancements
realtime: true,
subscriptionUrl: 'ws://api.example.com/updates',
cacheStrategy: "stale-while-revalidate",
cacheTime: 10 60 1000,
backgroundRefetch: true,
enableMetrics: true,
onMetrics: (metrics) => console.log(metrics)
}
);
`$3
Infinite scroll with universal pagination support and enhancements.
`typescript
import { PaginationAdapters } from 'react-data-cache';const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
// High Priority Enhancements
updateOptimistically,
retry,
retryCount,
syncStatus,
// Medium Priority Enhancements
isConnected,
metrics
} = useUniversalInfiniteQuery(
'posts',
async (pageParam, signal) => {
const response = await fetch(
/api/posts?page=${pageParam}, { signal });
return response.json();
},
{
...PaginationAdapters.offsetBased(),
// All enhancement options available here too
optimisticUpdates: true,
retryAttempts: 3,
backgroundSync: true,
realtime: true,
enableMetrics: true
}
);
`$3
`typescript
import {
prefetchData,
prefetchMulti,
prefetchWithStrategy,
prefetchInBackground
} from 'react-data-cache';// Prefetch with retry logic
prefetchData('posts', fetchPosts, {
retryConfig: {
attempts: 3,
delay: 1000,
exponentialBackoff: true
}
});
// Prefetch with cache strategy
prefetchWithStrategy('user-123', fetchUser, 'stale-while-revalidate');
// Background prefetching
const cleanup = prefetchInBackground('live-data', fetchLiveData, 30000);
`๐จ Pagination Adapters
The library provides pre-built adapters for common pagination patterns:
$3
`typescript
PaginationAdapters.offsetBased()
`$3
`typescript
PaginationAdapters.cursorBased()
`$3
`typescript
PaginationAdapters.linkBased()
`$3
`typescript
PaginationAdapters.custom({
selectData: (response) => response.items,
getNext: (response, currentOffset = 0) => {
return response.hasMore ? currentOffset + response.items.length : undefined;
},
initialParam: 0
})
`๐ State Management
The library uses a centralized cache system with the following states:
- idle - Initial state, no data loaded
- loading - Fetch in progress
- success - Data loaded successfully
- error - Fetch failed
- isRefetching - Refetch in progress (preserves existing data)
โก Performance Features
- Efficient Caching - Map-based cache with O(1) lookup
- Request Cancellation - AbortController integration for performance
- Event-Driven Updates - Cross-component state synchronization
- Stale-Time Control - Intelligent refetching based on data age
- Memory Management - Proper cleanup and leak prevention
- Performance Monitoring - Built-in metrics and analytics
- Advanced Caching - Multiple cache strategies for different use cases
๐ ๏ธ Advanced Usage
$3
`typescript
const { data } = useData(
user-${userId},
fetchUser,
{ enabled: !!userId }
);
`$3
`typescript
const handleLike = () => {
updateOptimistically(
{ likes: data.likes + 1 },
async () => {
await fetch(/api/posts/${postId}/like, { method: 'POST' });
}
);
};
`$3
`typescript
useEffect(() => {
const interval = setInterval(refetch, 60000); // Refetch every minute
return () => clearInterval(interval);
}, [refetch]);
`๐ง Configuration Options
$3
- staleTime - How long data is considered fresh (default: 5 seconds)
- refetchOnMount - Whether to refetch when component mounts (default: false)
- noCache - Bypass cache entirely (default: false)#### High Priority Enhancement Options
-
optimisticUpdates - Enable optimistic updates (default: false)
- retryAttempts - Number of retry attempts (default: 0)
- retryDelay - Delay between retries in ms (default: 1000)
- exponentialBackoff - Use exponential backoff (default: true)
- onError - Custom error handler function
- backgroundSync - Enable background sync (default: false)
- offlineSupport - Enable offline support (default: false)#### Medium Priority Enhancement Options
-
realtime - Enable real-time subscriptions (default: false)
- subscriptionUrl - WebSocket URL for real-time updates
- onUpdate - Callback for real-time updates
- cacheStrategy - Cache strategy ("default", "stale-while-revalidate", "cache-first", "network-first")
- cacheTime - How long to cache data (default: 5 minutes)
- backgroundRefetch - Enable background refetching (default: false)
- enableMetrics - Enable performance monitoring (default: false)
- onMetrics - Callback for performance metrics$3
- select - Extract items from API response
- getNextPageParam - Determine next page parameter
- getPreviousPageParam - Determine previous page parameter (for bidirectional)
- initialPageParam - Initial page parameter
- transformPage - Transform each page response before storing
- hasNextPage - Check if there are more pages (fallback)
- staleTime - How long data is considered fresh
- refetchOnMount - Whether to refetch when component mounts
- enabled - Whether to enable the query
- All enhancement options from useData are also available๐งช Examples
See the User Documentation for comprehensive examples including:
- Basic data fetching
- Error handling
- Infinite scroll implementations
- Prefetching strategies
- Performance optimization
- Type safety examples
- Complete application examples
- NEW: Enhanced features examples
๐ Troubleshooting
Common issues and solutions:
$3
`typescript
// Use appropriate stale time or manual refetch
const { data, refetch } = useData('key', fetchFn, {
staleTime: 0, // Always consider data stale
refetchOnMount: true
});
`$3
`typescript
// Provide explicit types
const { data } = useData('user', fetchUser);
``We welcome contributions! Please see our Contributing Guidelines and Developer Documentation for details.
MIT License - see LICENSE for details.
- ๐ User Documentation - Complete usage guide
- ๐ง Developer Documentation - Architecture details
- ๐ Issues - Report bugs or request features
- ๐ฌ Discussions - Ask questions and share ideas
- [x] Optimistic updates with rollback
- [x] Advanced error recovery and retry logic
- [x] Background sync and offline support
- [x] Real-time subscriptions
- [x] Advanced caching strategies
- [x] Performance monitoring
- [ ] Request queuing and batching
- [ ] Server-side rendering (SSR) support
- [ ] GraphQL integration
- [ ] Middleware system
---
Built with โค๏ธ for the React community