React bindings to work with persisters in TanStack/react-query
—
The PersistQueryClientProvider component provides React-specific persistence capabilities by wrapping the standard QueryClientProvider with automatic cache restoration and persistence subscription.
Main React provider component that manages the complete persistence lifecycle for React Query cache.
/**
* React provider component that wraps QueryClientProvider to add persistence capabilities
* Automatically restores cache on mount and subscribes to changes for continuous persistence
* @param props - Component props including persist options and callbacks
* @returns JSX element providing persistence context
*/
function PersistQueryClientProvider(props: PersistQueryClientProviderProps): React.JSX.Element;
interface PersistQueryClientProviderProps extends QueryClientProviderProps {
/** Persistence configuration options (queryClient is automatically provided) */
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>;
/** Optional callback executed after successful cache restoration */
onSuccess?: () => Promise<unknown> | unknown;
/** Optional callback executed after failed cache restoration */
onError?: () => Promise<unknown> | unknown;
}Usage Examples:
import React from 'react';
import { QueryClient } from '@tanstack/react-query';
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
const queryClient = new QueryClient();
// Basic usage
function App() {
return (
<PersistQueryClientProvider
client={queryClient}
persistOptions={{ persister: myPersister }}
>
<MyAppComponents />
</PersistQueryClientProvider>
);
}
// With success/error handling
function AppWithCallbacks() {
const handleRestoreSuccess = () => {
console.log('Query cache restored successfully');
// Optional: trigger app-specific logic after restoration
};
const handleRestoreError = () => {
console.error('Failed to restore query cache');
// Optional: show user notification or fallback behavior
};
return (
<PersistQueryClientProvider
client={queryClient}
persistOptions={{
persister: myPersister,
maxAge: 1000 * 60 * 60 * 24, // 24 hours
buster: 'v1.0.0' // invalidate old caches
}}
onSuccess={handleRestoreSuccess}
onError={handleRestoreError}
>
<MyAppComponents />
</PersistQueryClientProvider>
);
}
// With custom hydration options
function AppWithHydrationOptions() {
return (
<PersistQueryClientProvider
client={queryClient}
persistOptions={{
persister: myPersister,
hydrateOptions: {
// Only restore queries, not mutations
shouldDehydrateQuery: () => true,
shouldDehydrateMutation: () => false,
},
dehydrateOptions: {
// Custom dehydration settings for persistence
shouldDehydrateQuery: (query) => query.state.status === 'success',
}
}}
>
<MyAppComponents />
</PersistQueryClientProvider>
);
}The component follows this lifecycle:
truepersistQueryClientRestore with provided optionsfalseThe provider uses IsRestoringProvider from @tanstack/react-query to communicate restoration state to child components.
import { useIsRestoring } from '@tanstack/react-query';
function MyComponent() {
const isRestoring = useIsRestoring();
if (isRestoring) {
return <div>Loading cached data...</div>;
}
return <div>App content</div>;
}The provider handles QueryClient changes correctly:
function AppWithClientSwitching() {
const [client, setClient] = useState(() => new QueryClient());
// When client changes, provider will:
// 1. Unsubscribe from old client
// 2. Restore cache in new client (if not already done)
// 3. Subscribe to new client changes
return (
<PersistQueryClientProvider
client={client}
persistOptions={{ persister: myPersister }}
>
<button onClick={() => setClient(new QueryClient())}>
Switch Client
</button>
<MyAppComponents />
</PersistQueryClientProvider>
);
}When restoration fails:
removeClient() method is called to clean up invalid dataonError callback is executed (if provided)The component is designed to work correctly in React StrictMode without duplicate restoration attempts or subscriptions.
Install with Tessl CLI
npx tessl i tessl/npm-tanstack--react-query-persist-client