Installation #
This utility comes as a separate package and is available under the '@tanstack/query-persist-client-core'
import.
1npm install @tanstack/query-persist-client-core
or
1pnpm add @tanstack/query-persist-client-core
or
1yarn add @tanstack/query-persist-client-core
or
1bun add @tanstack/query-persist-client-core
Note: This util is also included in the
@tanstack/react-query-persist-client
package, so you do not need to install it separately if you are using that package.
Usage #
- Import the
experimental_createPersister
function - Create a new
experimental_createPersister
- you can pass any
storage
to it that adheres to theAsyncStorage
orStorage
interface - the example below uses the async-storage from React Native.
- you can pass any
- Pass that
persister
as an option to your Query. This can be done either by passing it to thedefaultOptions
of theQueryClient
or to anyuseQuery
hook instance.- If you pass this
persister
asdefaultOptions
, all queries will be persisted to the providedstorage
. You can additionally narrow this down by passingfilters
. In contrast to thepersistClient
plugin, this will not persist the whole query client as a single item, but each query separately. As a key, the query hash is used. - If you provide this
persister
to a singleuseQuery
hook, only this Query will be persisted.
- If you pass this
This way, you do not need to store whole QueryClient
, but choose what is worth to be persisted in your application. Each query is lazily restored (when the Query is first used) and persisted (after each run of the queryFn
), so it does not need to be throttled. staleTime
is also respected after restoring the Query, so if data is considered stale
, it will be refetched immediately after restoring. If data is fresh
, the queryFn
will not run.
Garbage collecting a Query from memory does not affect the persisted data. That means Queries can be kept in memory for a shorter period of time to be more memory efficient. If they are used the next time, they will just be restored from the persistent storage again.
1import AsyncStorage from '@react-native-async-storage/async-storage'
2import { QueryClient } from '@tanstack/react-query'
3import { experimental_createPersister } from '@tanstack/query-persist-client-core'
4
5const queryClient = new QueryClient({
6 defaultOptions: {
7 queries: {
8 gcTime: 1000 * 30, // 30 seconds
9 persister: experimental_createPersister({
10 storage: AsyncStorage,
11 maxAge: 1000 * 60 * 60 * 12, // 12 hours
12 }),
13 },
14 },
15})
Adapted defaults #
The createPersister
plugin technically wraps the queryFn
, so it doesn't restore if the queryFn
doesn't run. In that way, it acts as a caching layer between the Query and the network. Thus, the networkMode
defaults to 'offlineFirst'
when a persister is used, so that restoring from the persistent storage can also happen even if there is no network connection.
API #
experimental_createPersister
#
1experimental_createPersister(options: StoragePersisterOptions)
Options
#
1export interface StoragePersisterOptions {
2 /** The storage client used for setting and retrieving items from cache.
3 * For SSR pass in `undefined`.
4 */
5 storage: AsyncStorage | Storage | undefined | null
6 /**
7 * How to serialize the data to storage.
8 * @default `JSON.stringify`
9 */
10 serialize?: (persistedQuery: PersistedQuery) => string
11 /**
12 * How to deserialize the data from storage.
13 * @default `JSON.parse`
14 */
15 deserialize?: (cachedString: string) => PersistedQuery
16 /**
17 * A unique string that can be used to forcefully invalidate existing caches,
18 * if they do not share the same buster string
19 */
20 buster?: string
21 /**
22 * The max-allowed age of the cache in milliseconds.
23 * If a persisted cache is found that is older than this
24 * time, it will be discarded
25 * @default 24 hours
26 */
27 maxAge?: number
28 /**
29 * Prefix to be used for storage key.
30 * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`.
31 */
32 prefix?: string
33 /**
34 * Filters to narrow down which Queries should be persisted.
35 */
36 filters?: QueryFilters
37}
38
39interface AsyncStorage {
40 getItem: (key: string) => Promise<string | undefined | null>
41 setItem: (key: string, value: string) => Promise<unknown>
42 removeItem: (key: string) => Promise<void>
43}
The default options are:
1{
2 prefix = 'tanstack-query',
3 maxAge = 1000 * 60 * 60 * 24,
4 serialize = JSON.stringify,
5 deserialize = JSON.parse,
6}