Dies ist eine Sammlung von Dienstprogrammen für die Interaktion mit "Persistern", die Ihren QueryClient für die spätere Verwendung speichern. Verschiedene Persister können verwendet werden, um Ihren Client und Cache in vielen verschiedenen Speicherschichten zu speichern.
WICHTIG - Damit die Persistenz ordnungsgemäß funktioniert, möchten Sie wahrscheinlich einen QueryClient mit einem gcTime-Wert übergeben, um den Standardwert während der Hydrierung (wie oben gezeigt) zu überschreiben.
Wenn er bei der Erstellung der QueryClient-Instanz nicht gesetzt ist, wird er bei der Hydrierung standardmäßig auf 300000 (5 Minuten) gesetzt, und der gespeicherte Cache wird nach 5 Minuten Inaktivität verworfen. Dies ist das Standardverhalten der Garbage Collection.
Er sollte auf denselben Wert oder einen höheren Wert als die maxAge-Option von persistQueryClient gesetzt werden. Wenn z. B. maxAge 24 Stunden (Standard) beträgt, dann sollte gcTime 24 Stunden oder länger sein. Wenn er niedriger als maxAge ist, greift die Garbage Collection und verwirft den gespeicherten Cache früher als erwartet.
Sie können ihm auch Infinity übergeben, um das Verhalten der Garbage Collection vollständig zu deaktivieren.
Aufgrund einer JavaScript-Beschränkung beträgt die maximal zulässige gcTime etwa 24 Tage, obwohl es möglich ist, diese Grenze mit timeoutManager.setTimeoutProvider zu umgehen.
const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Manchmal nehmen Sie Änderungen an Ihrer Anwendung oder Ihren Daten vor, die sofort alle zwischengespeicherten Daten ungültig machen. Wenn dies geschieht, können Sie eine buster-Zeichenfolge als Option übergeben. Wenn der gefundene Cache nicht dieselbe Buster-Zeichenfolge hat, wird er verworfen. Die folgenden Funktionen akzeptieren diese Option
persistQueryClient({ queryClient, persister, buster: buildHash })
persistQueryClientSave({ queryClient, persister, buster: buildHash })
persistQueryClientRestore({ queryClient, persister, buster: buildHash })
persistQueryClient({ queryClient, persister, buster: buildHash })
persistQueryClientSave({ queryClient, persister, buster: buildHash })
persistQueryClientRestore({ queryClient, persister, buster: buildHash })
Wenn Daten als eine der folgenden gefunden werden
wird die removeClient()-Funktion des Persisters aufgerufen und der Cache sofort verworfen.
Sie können dies verwenden, um den Cache zu den von Ihnen gewählten Zeitpunkten explizit zu speichern.
persistQueryClientSave({
queryClient,
persister,
buster = '',
dehydrateOptions = undefined,
})
persistQueryClientSave({
queryClient,
persister,
buster = '',
dehydrateOptions = undefined,
})
Führt persistQueryClientSave aus, wann immer sich der Cache für Ihren queryClient ändert. Zum Beispiel: Sie könnten die subscribe initiieren, wenn sich ein Benutzer anmeldet und "Angemeldet bleiben" wählt.
persistQueryClientSubscribe({
queryClient,
persister,
buster = '',
dehydrateOptions = undefined,
})
persistQueryClientSubscribe({
queryClient,
persister,
buster = '',
dehydrateOptions = undefined,
})
Sie können dies verwenden, um den Cache zu den von Ihnen gewählten Zeitpunkten wiederherzustellen.
persistQueryClientRestore({
queryClient,
persister,
maxAge = 1000 * 60 * 60 * 24, // 24 hours
buster = '',
hydrateOptions = undefined,
})
persistQueryClientRestore({
queryClient,
persister,
maxAge = 1000 * 60 * 60 * 24, // 24 hours
buster = '',
hydrateOptions = undefined,
})
Nimmt die folgenden Aktionen vor
Diese Funktionalität ist aus Version 3.x erhalten geblieben.
persistQueryClient({
queryClient,
persister,
maxAge = 1000 * 60 * 60 * 24, // 24 hours
buster = '',
hydrateOptions = undefined,
dehydrateOptions = undefined,
})
persistQueryClient({
queryClient,
persister,
maxAge = 1000 * 60 * 60 * 24, // 24 hours
buster = '',
hydrateOptions = undefined,
dehydrateOptions = undefined,
})
Alle verfügbaren Optionen sind wie folgt
interface PersistQueryClientOptions {
/** The QueryClient to persist */
queryClient: QueryClient
/** The Persister interface for storing and restoring the cache
* to/from a persisted location */
persister: Persister
/** The max-allowed age of the cache in milliseconds.
* If a persisted cache is found that is older than this
* time, it will be **silently** discarded
* (defaults to 24 hours) */
maxAge?: number
/** A unique string that can be used to forcefully
* invalidate existing caches if they do not share the same buster string */
buster?: string
/** The options passed to the hydrate function
* Not used on `persistQueryClientSave` or `persistQueryClientSubscribe` */
hydrateOptions?: HydrateOptions
/** The options passed to the dehydrate function
* Not used on `persistQueryClientRestore` */
dehydrateOptions?: DehydrateOptions
}
interface PersistQueryClientOptions {
/** The QueryClient to persist */
queryClient: QueryClient
/** The Persister interface for storing and restoring the cache
* to/from a persisted location */
persister: Persister
/** The max-allowed age of the cache in milliseconds.
* If a persisted cache is found that is older than this
* time, it will be **silently** discarded
* (defaults to 24 hours) */
maxAge?: number
/** A unique string that can be used to forcefully
* invalidate existing caches if they do not share the same buster string */
buster?: string
/** The options passed to the hydrate function
* Not used on `persistQueryClientSave` or `persistQueryClientSubscribe` */
hydrateOptions?: HydrateOptions
/** The options passed to the dehydrate function
* Not used on `persistQueryClientRestore` */
dehydrateOptions?: DehydrateOptions
}
Es gibt tatsächlich drei verfügbare Schnittstellen
persistQueryClient versucht, den Cache wiederherzustellen und abonniert automatisch weitere Änderungen, wodurch Ihr Client mit dem bereitgestellten Speicher synchronisiert wird.
Die Wiederherstellung ist jedoch asynchron, da alle Persister von Natur aus asynchron sind. Das bedeutet, dass Sie, wenn Sie Ihre App rendern, während die Wiederherstellung läuft, in Race Conditions geraten könnten, wenn eine Abfrage gleichzeitig gemountet wird und abruft.
Darüber hinaus haben Sie keine Möglichkeit, sich abzumelden, wenn Sie Änderungen außerhalb des Lebenszyklus der React-Komponente abonnieren.
// 🚨 never unsubscribes from syncing
persistQueryClient({
queryClient,
persister: localStoragePersister,
})
// 🚨 happens at the same time as restoring
ReactDOM.createRoot(rootElement).render(<App />)
// 🚨 never unsubscribes from syncing
persistQueryClient({
queryClient,
persister: localStoragePersister,
})
// 🚨 happens at the same time as restoring
ReactDOM.createRoot(rootElement).render(<App />)
Für diesen Anwendungsfall können Sie den PersistQueryClientProvider verwenden. Er stellt sicher, dass die Abmeldung und Anmeldung korrekt gemäß dem Lebenszyklus der React-Komponente erfolgt, und er stellt auch sicher, dass Abfragen nicht zu fetchen beginnen, während wir noch wiederherstellen. Abfragen werden zwar weiterhin gerendert, sie werden aber in den fetchingState: 'idle' versetzt, bis die Daten wiederhergestellt sind. Dann werden sie erneut abgerufen, es sei denn, die wiederhergestellten Daten sind *frisch genug*, und initialData wird ebenfalls berücksichtigt. Er kann *anstelle* des normalen QueryClientProvider verwendet werden.
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
const persister = createAsyncStoragePersister({
storage: window.localStorage,
})
ReactDOM.createRoot(rootElement).render(
<PersistQueryClientProvider
client={queryClient}
persistOptions={{ persister }}
>
<App />
</PersistQueryClientProvider>,
)
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
const persister = createAsyncStoragePersister({
storage: window.localStorage,
})
ReactDOM.createRoot(rootElement).render(
<PersistQueryClientProvider
client={queryClient}
persistOptions={{ persister }}
>
<App />
</PersistQueryClientProvider>,
)
PersistQueryClientProvider nimmt dieselben Props entgegen wie QueryClientProvider, und zusätzlich
Wenn Sie den PersistQueryClientProvider verwenden, können Sie auch den useIsRestoring Hook zusammen damit verwenden, um zu prüfen, ob eine Wiederherstellung gerade im Gange ist. useQuery und ähnliche Funktionen prüfen dies auch intern, um Race Conditions zwischen der Wiederherstellung und neu gemounteten Abfragen zu vermeiden.
Persister haben die folgenden Schnittstellen
export interface Persister {
persistClient(persistClient: PersistedClient): Promisable<void>
restoreClient(): Promisable<PersistedClient | undefined>
removeClient(): Promisable<void>
}
export interface Persister {
persistClient(persistClient: PersistedClient): Promisable<void>
restoreClient(): Promisable<PersistedClient | undefined>
removeClient(): Promisable<void>
}
Persisted Client-Einträge haben die folgende Schnittstelle
export interface PersistedClient {
timestamp: number
buster: string
clientState: DehydratedState
}
export interface PersistedClient {
timestamp: number
buster: string
clientState: DehydratedState
}
Sie können diese importieren (um einen Persister zu erstellen)
import {
PersistedClient,
Persister,
} from '@tanstack/react-query-persist-client'
import {
PersistedClient,
Persister,
} from '@tanstack/react-query-persist-client'
Sie können auf jede beliebige Weise persistieren. Hier ist ein Beispiel für die Erstellung eines Indexed DB-Persisters. Im Vergleich zur Web Storage API ist Indexed DB schneller, speichert mehr als 5 MB und erfordert keine Serialisierung. Das bedeutet, dass es JavaScript-native Typen wie Date und File problemlos speichern kann.
import { get, set, del } from 'idb-keyval'
import {
PersistedClient,
Persister,
} from '@tanstack/react-query-persist-client'
/**
* Creates an Indexed DB persister
* @see https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
*/
export function createIDBPersister(idbValidKey: IDBValidKey = 'reactQuery') {
return {
persistClient: async (client: PersistedClient) => {
await set(idbValidKey, client)
},
restoreClient: async () => {
return await get<PersistedClient>(idbValidKey)
},
removeClient: async () => {
await del(idbValidKey)
},
} satisfies Persister
}
import { get, set, del } from 'idb-keyval'
import {
PersistedClient,
Persister,
} from '@tanstack/react-query-persist-client'
/**
* Creates an Indexed DB persister
* @see https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
*/
export function createIDBPersister(idbValidKey: IDBValidKey = 'reactQuery') {
return {
persistClient: async (client: PersistedClient) => {
await set(idbValidKey, client)
},
restoreClient: async () => {
return await get<PersistedClient>(idbValidKey)
},
removeClient: async () => {
await del(idbValidKey)
},
} satisfies Persister
}