React bindings to work with persisters in TanStack/react-query
—
Core persistence functions provide low-level control over cache restoration, saving, and subscription management. These functions are re-exported from @tanstack/query-persist-client-core for direct use when you need manual control over the persistence lifecycle.
High-level function that combines restoration and subscription into a single operation.
/**
* Restores persisted data to QueryCache and persists further changes
* Combines restoration and subscription into a single operation
* @param props - Complete persistence configuration
* @returns Tuple of [unsubscribe function, restore promise]
*/
function persistQueryClient(props: PersistQueryClientOptions): [() => void, Promise<void>];Usage Example:
import { QueryClient } from '@tanstack/react-query';
import { persistQueryClient } from '@tanstack/react-query-persist-client';
const queryClient = new QueryClient();
const [unsubscribe, restorePromise] = persistQueryClient({
queryClient,
persister: myPersister,
maxAge: 1000 * 60 * 60 * 24, // 24 hours
buster: 'v1.0.0',
});
// Wait for restoration to complete
restorePromise
.then(() => console.log('Cache restored'))
.catch(() => console.log('Restoration failed'));
// Later, stop persistence
unsubscribe();Restores persisted data to the QueryCache from the persister.
/**
* Restores persisted data to the QueryCache
* Validates data age and buster string before restoration
* Automatically removes expired or invalid data
* @param options - Restoration configuration options
* @returns Promise that resolves when restoration completes
*/
function persistQueryClientRestore(options: PersistedQueryClientRestoreOptions): Promise<void>;Usage Example:
import { persistQueryClientRestore } from '@tanstack/react-query-persist-client';
await persistQueryClientRestore({
queryClient,
persister: myPersister,
maxAge: 1000 * 60 * 60, // 1 hour
buster: 'v2.0.0', // invalidate caches from v1.x
hydrateOptions: {
// Control which queries get restored
shouldDehydrateQuery: (query) => query.queryKey[0] === 'user-data',
},
});Saves current QueryCache state to the persister.
/**
* Persists current QueryCache data using the persister
* Dehydrates cache using provided options and saves with timestamp
* @param options - Save configuration options
* @returns Promise that resolves when save completes
*/
function persistQueryClientSave(options: PersistedQueryClientSaveOptions): Promise<void>;Usage Example:
import { persistQueryClientSave } from '@tanstack/react-query-persist-client';
await persistQueryClientSave({
queryClient,
persister: myPersister,
buster: 'v1.0.0',
dehydrateOptions: {
// Only save successful queries
shouldDehydrateQuery: (query) => query.state.status === 'success',
// Don't save mutations
shouldDehydrateMutation: () => false,
},
});Subscribes to QueryCache and MutationCache changes for automatic persistence.
/**
* Subscribe to QueryCache and MutationCache changes for automatic persistence
* Triggers save operations when cache contents change
* @param props - Subscription configuration options
* @returns Unsubscribe function to stop monitoring
*/
function persistQueryClientSubscribe(props: PersistedQueryClientSaveOptions): () => void;Usage Example:
import { persistQueryClientSubscribe } from '@tanstack/react-query-persist-client';
const unsubscribe = persistQueryClientSubscribe({
queryClient,
persister: myPersister,
buster: 'v1.0.0',
dehydrateOptions: {
shouldDehydrateQuery: (query) => {
// Only persist queries that have been successful for at least 5 minutes
const age = Date.now() - query.state.dataUpdatedAt;
return query.state.status === 'success' && age > 5 * 60 * 1000;
},
},
});
// Later, stop subscribing
unsubscribe();import {
persistQueryClientRestore,
persistQueryClientSave,
persistQueryClientSubscribe
} from '@tanstack/react-query-persist-client';
class CacheManager {
private unsubscribe?: () => void;
async initialize() {
// Restore cache on app startup
await persistQueryClientRestore({
queryClient: this.queryClient,
persister: this.persister,
maxAge: this.config.maxAge,
});
// Start automatic persistence
this.startPersistence();
}
startPersistence() {
this.unsubscribe = persistQueryClientSubscribe({
queryClient: this.queryClient,
persister: this.persister,
dehydrateOptions: this.config.dehydrateOptions,
});
}
stopPersistence() {
this.unsubscribe?.();
this.unsubscribe = undefined;
}
async forceSave() {
await persistQueryClientSave({
queryClient: this.queryClient,
persister: this.persister,
dehydrateOptions: this.config.dehydrateOptions,
});
}
}// Only persist in certain conditions
const conditionalPersister = {
persistClient: async (client) => {
if (shouldPersist()) {
await actualPersister.persistClient(client);
}
},
restoreClient: () => actualPersister.restoreClient(),
removeClient: () => actualPersister.removeClient(),
};
function shouldPersist() {
return !window.navigator.userAgent.includes('Bot') &&
localStorage.getItem('persist-enabled') === 'true';
}async function robustRestore() {
try {
await persistQueryClientRestore({
queryClient,
persister: primaryPersister,
maxAge: 1000 * 60 * 60 * 24,
});
} catch (error) {
console.warn('Primary restore failed, trying backup');
try {
await persistQueryClientRestore({
queryClient,
persister: backupPersister,
maxAge: 1000 * 60 * 60 * 24,
});
} catch (backupError) {
console.warn('All restore attempts failed');
// Continue with fresh cache
}
}
}Install with Tessl CLI
npx tessl i tessl/npm-tanstack--react-query-persist-client