Utilities for persisting TanStack Query cache data to various storage backends with restore functionality
—
Complete query client persistence system that automatically saves and restores entire query cache state. This approach is ideal for maintaining full application state across browser sessions, app restarts, or navigation.
Main function that combines restoration and subscription for complete persistence lifecycle management.
/**
* Restores persisted data to QueryCache and persists further changes
* @param props - Configuration options for persistence
* @returns Tuple of [unsubscribe function, restore promise]
*/
function persistQueryClient(
props: PersistQueryClientOptions
): [() => void, Promise<void>];Usage Example:
import { QueryClient } from "@tanstack/query-core";
import { persistQueryClient } from "@tanstack/query-persist-client-core";
const queryClient = new QueryClient();
const persister = {
persistClient: async (client) => {
localStorage.setItem("app-cache", JSON.stringify(client));
},
restoreClient: async () => {
const stored = localStorage.getItem("app-cache");
return stored ? JSON.parse(stored) : undefined;
},
removeClient: async () => {
localStorage.removeItem("app-cache");
}
};
// Set up complete persistence
const [unsubscribe, restorePromise] = persistQueryClient({
queryClient,
persister,
buster: "app-v2.1",
maxAge: 1000 * 60 * 60 * 24, // 24 hours
dehydrateOptions: {
shouldDehydrateQuery: (query) => query.state.status === 'success'
},
hydrateOptions: {
defaultOptions: {
queries: { staleTime: 1000 * 60 * 5 } // 5 minutes
}
}
});
// Wait for restoration to complete
try {
await restorePromise;
console.log("Cache restored successfully");
} catch (error) {
console.error("Cache restoration failed:", error);
}
// Clean up when component unmounts or app closes
unsubscribe();Restores persisted data to the QueryCache with validation and error handling.
/**
* Restores persisted data to the QueryCache
* - data obtained from persister.restoreClient
* - data is hydrated using hydrateOptions
* If data is expired, busted, empty, or throws, it runs persister.removeClient
* @param options - Restoration configuration options
*/
async function persistQueryClientRestore(
options: PersistedQueryClientRestoreOptions
): Promise<void>;Usage Example:
import { persistQueryClientRestore } from "@tanstack/query-persist-client-core";
// Manual restoration with custom options
await persistQueryClientRestore({
queryClient,
persister,
maxAge: 1000 * 60 * 60 * 12, // 12 hours instead of default 24
buster: "custom-version",
hydrateOptions: {
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 10, // 10 minutes
cacheTime: 1000 * 60 * 30 // 30 minutes
}
}
}
});Persists current query cache data using the provided persister.
/**
* Persists data from the QueryCache
* - data dehydrated using dehydrateOptions
* - data is persisted using persister.persistClient
* @param options - Save configuration options
*/
async function persistQueryClientSave(
options: PersistedQueryClientSaveOptions
): Promise<void>;Usage Example:
import { persistQueryClientSave } from "@tanstack/query-persist-client-core";
// Manual save with selective dehydration
await persistQueryClientSave({
queryClient,
persister,
buster: "manual-save-v1",
dehydrateOptions: {
shouldDehydrateQuery: (query) => {
// Only persist successful queries that aren't stale
return query.state.status === 'success' && !query.isStale();
},
shouldDehydrateMutation: () => false // Don't persist mutations
}
});Creates a subscription to query and mutation cache changes for automatic persistence.
/**
* Subscribe to QueryCache and MutationCache updates (for persisting)
* @param props - Subscription configuration options
* @returns An unsubscribe function to discontinue monitoring
*/
function persistQueryClientSubscribe(
props: PersistedQueryClientSaveOptions
): () => void;Usage Example:
import { persistQueryClientSubscribe } from "@tanstack/query-persist-client-core";
// Set up automatic persistence on cache changes
const unsubscribe = persistQueryClientSubscribe({
queryClient,
persister,
buster: "auto-persist-v1",
dehydrateOptions: {
shouldDehydrateQuery: (query) => query.state.status === 'success'
}
});
// Later, stop automatic persistence
unsubscribe();interface PersistedQueryClientRestoreOptions
extends PersistQueryClientRootOptions {
/** The max-allowed age of the cache in milliseconds.
* If a persisted cache is found that is older than this
* time, it will be discarded */
maxAge?: number;
/** The options passed to the hydrate function */
hydrateOptions?: HydrateOptions;
}interface PersistedQueryClientSaveOptions
extends PersistQueryClientRootOptions {
/** The options passed to the dehydrate function */
dehydrateOptions?: DehydrateOptions;
}interface PersistQueryClientRootOptions {
/** The QueryClient to persist */
queryClient: QueryClient;
/** The Persister interface for storing and restoring the cache
* to/from a persisted location */
persister: Persister;
/** A unique string that can be used to forcefully
* invalidate existing caches if they do not share the same buster string */
buster?: string;
}interface PersistQueryClientOptions
extends PersistedQueryClientRestoreOptions,
PersistedQueryClientSaveOptions,
PersistQueryClientRootOptions {}The persistence system includes robust error handling:
maxAge are automatically discardedAll persistence operations are non-blocking and will not crash your application if storage fails.
Install with Tessl CLI
npx tessl i tessl/npm-tanstack--query-persist-client-core