BitcoinQueryProvider
React Query provider for efficient data caching and state management in Bitcoin applications
A React Query-based provider that enables efficient data caching, synchronization, and state management for BigBlocks components. It provides optimized caching for market data, wallet operations, and social features.
Installation
npx bigblocks add bitcoin-query-provider
Import
import { BitcoinQueryProvider } from 'bigblocks';
Props
Prop | Type | Required | Default | Description |
---|---|---|---|---|
children | React.ReactNode | Yes | - | Child components |
queryClient | QueryClient | No | Default client | Custom React Query client |
Basic Usage
import { BitcoinQueryProvider } from 'bigblocks';
function App() {
return (
<BitcoinQueryProvider>
<BitcoinThemeProvider>
<BitcoinAuthProvider config={{ apiUrl: '/api' }}>
<YourAppContent />
</BitcoinAuthProvider>
</BitcoinThemeProvider>
</BitcoinQueryProvider>
);
}
Advanced Usage
Custom Query Client
import { BitcoinQueryProvider } from 'bigblocks';
import { QueryClient } from '@tanstack/react-query';
export default function CustomQueryApp() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5 minutes
cacheTime: 10 * 60 * 1000, // 10 minutes
refetchOnWindowFocus: false,
retry: (failureCount, error) => {
if (error.status === 401) return false;
return failureCount < 3;
},
},
mutations: {
retry: 1,
},
},
});
return (
<BitcoinQueryProvider queryClient={queryClient}>
<App />
</BitcoinQueryProvider>
);
}
Production Configuration
import { BitcoinQueryProvider } from 'bigblocks';
import { QueryClient } from '@tanstack/react-query';
export default function ProductionApp() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 2 * 60 * 1000, // 2 minutes
cacheTime: 15 * 60 * 1000, // 15 minutes
refetchOnWindowFocus: true,
refetchOnReconnect: true,
networkMode: 'offlineFirst',
retry: (failureCount, error) => {
// Don't retry client errors
if (error.status >= 400 && error.status < 500) {
return false;
}
return failureCount < 2;
},
},
},
});
// Set specific defaults for different query types
queryClient.setQueryDefaults(['balance'], {
staleTime: 30 * 1000, // Balance data should be fresh
refetchInterval: 60 * 1000, // Auto-refresh every minute
});
queryClient.setQueryDefaults(['market'], {
staleTime: 5 * 60 * 1000, // Market data can be cached longer
});
return (
<BitcoinQueryProvider queryClient={queryClient}>
<App />
</BitcoinQueryProvider>
);
}
With Error Handling
import { BitcoinQueryProvider } from 'bigblocks';
import { QueryClient, QueryCache } from '@tanstack/react-query';
export default function ErrorHandlingApp() {
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (error) => {
console.error('Query error:', error);
if (error.status === 401) {
// Handle authentication errors
window.location.href = '/signin';
}
},
}),
defaultOptions: {
mutations: {
onError: (error) => {
console.error('Mutation failed:', error);
// Show error notification
toast.error('Operation failed. Please try again.');
},
},
},
});
return (
<BitcoinQueryProvider queryClient={queryClient}>
<App />
</BitcoinQueryProvider>
);
}
With DevTools
import { BitcoinQueryProvider } from 'bigblocks';
import { QueryClient } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
export default function DevelopmentApp() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 0, // Always refetch in development
refetchOnWindowFocus: false, // Disable for development
},
},
});
return (
<BitcoinQueryProvider queryClient={queryClient}>
<App />
{process.env.NODE_ENV === 'development' && (
<ReactQueryDevtools initialIsOpen={false} />
)}
</BitcoinQueryProvider>
);
}
Common Patterns
Provider Nesting Order
import {
BitcoinQueryProvider,
BitcoinThemeProvider,
BitcoinAuthProvider
} from 'bigblocks';
// Correct nesting order (outside to inside):
// 1. BitcoinQueryProvider (provides React Query context)
// 2. BitcoinThemeProvider (provides theme context)
// 3. BitcoinAuthProvider (uses React Query for auth state)
export default function App() {
return (
<BitcoinQueryProvider>
<BitcoinThemeProvider defaultTheme="orange">
<BitcoinAuthProvider config={{ apiUrl: '/api' }}>
<YourApp />
</BitcoinAuthProvider>
</BitcoinThemeProvider>
</BitcoinQueryProvider>
);
}
Memory Optimization
import { BitcoinQueryProvider } from 'bigblocks';
import { QueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';
export default function MemoryOptimizedApp() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 5 * 60 * 1000, // Shorter cache time
staleTime: 1 * 60 * 1000, // Data stales quickly
refetchOnMount: 'always', // Always fetch fresh data
},
},
});
// Clear cache on logout
useEffect(() => {
const handleLogout = () => {
queryClient.clear();
};
window.addEventListener('logout', handleLogout);
return () => window.removeEventListener('logout', handleLogout);
}, [queryClient]);
return (
<BitcoinQueryProvider queryClient={queryClient}>
<App />
</BitcoinQueryProvider>
);
}
With Suspense
import { BitcoinQueryProvider } from 'bigblocks';
import { QueryClient } from '@tanstack/react-query';
import { Suspense } from 'react';
export default function SuspenseApp() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
suspense: true, // Enable suspense mode
useErrorBoundary: true, // Use error boundaries
},
},
});
return (
<BitcoinQueryProvider queryClient={queryClient}>
<ErrorBoundary fallback={<ErrorPage />}>
<Suspense fallback={<LoadingSpinner />}>
<App />
</Suspense>
</ErrorBoundary>
</BitcoinQueryProvider>
);
}
Benefits
1. Request Deduplication
Multiple components requesting the same data will result in a single network request:
// Both components will share the same query
function ComponentA() {
const { data } = useQuery({ queryKey: ['market'] });
return <div>{data}</div>;
}
function ComponentB() {
const { data } = useQuery({ queryKey: ['market'] });
return <div>{data}</div>;
}
2. Background Updates
Data is refetched in the background when it becomes stale:
// Data will be cached and updated in background
const { data, isStale } = useQuery({
queryKey: ['balance'],
staleTime: 30 * 1000, // Consider stale after 30 seconds
});
3. Optimistic Updates
Update UI immediately while the mutation is in progress:
const mutation = useMutation({
mutationFn: updateProfile,
onMutate: async (newData) => {
// Optimistically update the cache
queryClient.setQueryData(['profile'], newData);
},
});
4. Offline Support
Cached data remains available when offline:
const { data, isLoading, isError } = useQuery({
queryKey: ['profile'],
networkMode: 'offlineFirst', // Use cache when offline
});
Working with BigBlocks Components
The BitcoinQueryProvider is required for these components:
- MarketTable - Market listings with real-time updates
- PostButton - Social post creation
- SocialFeed - Social content feed
- WalletOverview - Wallet balance and transactions
- SendBSVButton - Transaction operations
Example with market components:
import {
BitcoinQueryProvider,
MarketTable,
CreateListingButton
} from 'bigblocks';
export default function MarketplaceApp() {
return (
<BitcoinQueryProvider>
<BitcoinAuthProvider config={{ apiUrl: '/api' }}>
<CreateListingButton />
<MarketTable />
</BitcoinAuthProvider>
</BitcoinQueryProvider>
);
}
Troubleshooting
Missing QueryClient Error
Error: No QueryClient set, use QueryClientProvider to set one
Solution: Ensure BitcoinQueryProvider wraps all components that need React Query.
Stale Closure Issues
// ❌ Bad - stale closure
const queryClient = new QueryClient();
function App() {
return <BitcoinQueryProvider queryClient={queryClient}>...</BitcoinQueryProvider>;
}
// ✅ Good - fresh instance
function App() {
const queryClient = new QueryClient();
return <BitcoinQueryProvider queryClient={queryClient}>...</BitcoinQueryProvider>;
}
Cache Not Clearing
// Clear all queries
queryClient.clear();
// Clear specific queries
queryClient.removeQueries({ queryKey: ['market'] });
// Invalidate to refetch
queryClient.invalidateQueries({ queryKey: ['balance'] });
Best Practices
- Provider Order: Always place BitcoinQueryProvider at the root
- Query Keys: Use consistent, hierarchical query keys
- Stale Times: Set appropriate stale times based on data type
- Error Handling: Implement global error handling
- Memory Management: Clear cache on logout
Related Components
- BitcoinAuthProvider - Authentication provider
- BitcoinThemeProvider - Theme provider
- MarketTable - Requires query provider
- SocialFeed - Requires query provider
API Reference
QueryClient Configuration
interface QueryClientConfig {
defaultOptions?: {
queries?: {
cacheTime?: number;
staleTime?: number;
refetchOnWindowFocus?: boolean;
refetchOnReconnect?: boolean;
refetchOnMount?: boolean | 'always';
retry?: boolean | number | ((failureCount: number, error: any) => boolean);
retryDelay?: number | ((attemptIndex: number) => number);
networkMode?: 'online' | 'always' | 'offlineFirst';
};
mutations?: {
retry?: boolean | number;
retryDelay?: number;
networkMode?: 'online' | 'always' | 'offlineFirst';
};
};
}
Notes for Improvement
Simplified Implementation: The actual component is a simple wrapper around React Query's QueryClientProvider. The prompt described many advanced features that would be implemented in the consuming application rather than the provider itself. The actual component focuses on:
- Providing React Query context
- Working around bundler limitations
- Ensuring compatibility with BigBlocks components
The advanced query patterns, real-time updates, and optimization strategies described in the prompt would be implemented by developers using the provider, not within the provider component itself.