persistQueryClient 플러그인
persistQueryClient는 나중에 사용할 수 있도록 쿼리 클라이언트를 저장하는 perister와 상호 작용하기 위한 유틸리티 집합입니다. 다양한 persister들를 사용하여 클라이언트 및 캐시를 다양한 스토리지 레이어에 저장할 수 있습니다.persist가 제대로 작동하려면 hydration 도중에 디폴트값을 재정의하기 위해 QueryClient에 cacheTime 값을 전달해야 될 수 있습니다.
QueryClient 인스턴스를 만들 때 cacheTime 값을 설정하지 않으면 hydration를 위해 디폴트 값이 300000(5분)으로 설정되며 저장된 캐시는 5분 동안 비활성화된 후 삭제됩니다.
persistQueryClient 의 maxAge 옵션의 값보다 같거나 큰 값으로 설정해야 합니다.
maxAge가 24시간(기본값)이면 cacheTime은 24시간 이상이어야 합니다. maxAge보다 작으면 가비지 컬렉션이 시작되고 저장된 캐시가 예상보다 빨리 삭제됩니다.가바지 컬렉션을 작동하지 않게 하려면 Infinity 값으로 설정하면 됩니다.
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
buster 옵션을 전달할 수 있습니다. buster 문자열이 없으면 캐시가 삭제됩니다. 이 옵션을 사용할 수 있는 기능은 다음과 같습니다:persistQueryClient({ queryClient, persister, buster: buildHash })
persistQueryClientSave({ queryClient, persister, buster: buildHash })
persistQueryClientRestore({ queryClient, persister, buster: buildHash })
removeClient()가 호출되고 캐시가 즉시 삭제됩니다.persistQueryClientSavedehydrated 상태가 되고 저장됩니다. createSyncStoragePersister 및 createAsyncStoragePersister 는 throttle 합니다. 이 작업은 잠재적으로 비용이 많이 드는 쓰기 작업을 절약하기 위해 최대 1초마다 수행됩니다. 스로틀 타이밍을 사용자 지정하는 방법을 보려면 해당 문서를 검토하십시오.원하는 타이밍에 명시적으로 캐시에 persist 하기 위해 이렇게 사용할 수 있습니다.
persistQueryClientSave({ queryClient, persister, buster = '', dehydrateOptions = undefined, })
queryClient의 캐시가 변경될 때마다 persistQueryClientSave 가 실행됩니다. 예를 들어, 사용자가 로그인하고 "Remember me"를 확인할 때 subscribe를 시작할 수 있습니다.
unsubscribe 함수를 리턴합니다 : 모니터링을 중단하고 지속적인 캐시에 대한 업데이트를 종료하는 데 사용할 수 있습니다.unsubscribe 이후 persisted cache를 삭제하고 싶을 경우, 새로운 buster를 persistQueryClientRestore에 보낼 수 있는데 이 것이 persister 의 removeClient 함수의 트리거가 됩니다. 그리고 persisted cache 가 삭제됩니다.persistQueryClientSubscribe({
queryClient,
persister,
buster = '',
dehydrateOptions = undefined,
})
hydrate를 시도하여 쿼리 client 에 넘겨졌던 query cache 로 되돌립니다.maxAge 보다 오래된 경우, 캐시는 삭제됩니다. (이 타이밍은 커스터마이징 할수 있습니다.)원하는 타이밍에 캐시를 restore할때 이렇게 쓸수 있습니다.
persistQueryClientRestore({ queryClient, persister, maxAge = 1000 * 60 * 60 * 24, // 24 hours buster = '', hydrateOptions = undefined, })
다음 액션들을 취합니다
1. 모든 persisted cache 를 즉시 restore한다 (see persisteQueryClientRestore)
2. 쿼리 캐시를 구독하고 unsubscribe 함수를 리턴한다. (see persistQueryClientSubscribe)
persistQueryClient({
queryClient,
persister,
maxAge = 1000 * 60 * 60 * 24, // 24 hours
buster = '',
hydrateOptions = undefined,
dehydrateOptions = undefined,
})
interface PersistQueryClientOptions {
/** The QueryClient to persist */
queryClient: QueryClient
/** The Persister interface for storing and restoring the cache
* to/from a persisted location */
persister: Persister
/** maxAge: 최대 허용되는 캐싱 기간 (ms)
* 해당 시간보다 오래된 persisted 캐시는 스스로 삭제됩니다.
* (기본값 24시간) */
maxAge?: number
/** buster 는 유니크한 문자열.
* 만약 같은 buster string 을 갖지 않을 경우 강제로 캐시를 비활성시킵니다.
*/
buster?: string
/** hydrateOptions 는 hydrate 함수에 넘겨집니다.
* `persistQueryClientSave` 나 `persistQueryClientSubscribe`에 사용X */
hydrateOptions?: HydrateOptions
/** dehydrateOptions 는 dehydrate 함수에 넘겨집니다.
* `persistQueryClientRestore`에 사용X*/
dehydrateOptions?: DehydrateOptions
}
실제로 사용할 수 있는 인터페이스는 세 가지입니다:
PersistedQueryClientSaveOptions is used for persistQueryClientSave and persistQueryClientSubscribe(doesn't use hydrateOptions).PersistedQueryClientRestoreOptions is used for persistQueryClientRestore (doesn't use dehydrateOptions).PersistQueryClientOptions is used for persistQueryClientpersistQueryClient는 캐시 restore을 시도하고 추가 변경사항에 자동으로 subscribe하여 제공된 storage에 클라이언트를 동기화합니다.restoring은 비동기적입니다. 모든 persister가 비동기적이기 때문입니다. 즉, restore하는 동안 App을 렌더링하면 쿼리가 mount되고 동시에 fetch해올 경우 경쟁 상태가 될 수 있습니다.// 🚨 절대로 동기 상태를 취소할 수 없습니다
// never unsubscribes from syncing
persistQueryClient({
queryClient,
persister: localStoragePersister,
})
// 🚨 restoring과 동시에 발생합니다
ReactDOM.createRoot(rootElement).render(<App />)
PersisteQueryClientProvider 를 사용해서 React 컴포넌트의 수명 주기에 따라 올바르게 subscribe/unsubscribe할 수 있으며, restore 중에도 쿼리 fetch가 시작되지 않습니다.fetchingState: idle 상태가 됩니다.fresh가 아니면, 다시 refetch하고 initialData도 respect 됩니다. QueryClientProvider 대신 사용할 수 있습니다:import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
const persister = createSyncStoragePersister({
storage: window.localStorage,
})
ReactDOM.createRoot(rootElement).render(
<PersistQueryClientProvider
client={queryClient}
persistOptions={{ persister }}
>
<App />
</PersistQueryClientProvider>
)
PersistQueryClientProvider 는 QueryClientProvider 와 같은 props 를 갖고, 추가적으로 다음 props 를 갖습니다.
persistOptions: PersistQueryClientOptions : persistQueryClient 에 넘길수 있는 옵션들 (QueryClient 자신은 제외)onSuccess?: () => voidPersistQueryClientProvider를 사용하고 싶으면, useIsRestoring 훅도 함께 사용하여 restore가 현재 진행 중인지 확인할 수도 있습니다. Persister의 인터페이스
export interface Persister {
persistClient(persistClient: PersistedClient): Promisable<void>
restoreClient(): Promisable<PersistedClient | undefined>
removeClient(): Promisable<void>
}
Persisted Client entries 들은 다음 인터페이스를 갖습니다.
export interface PersistedClient {
timestamp: number
buster: string
cacheState: any
}
persister 를 빌드하기 위해 다음을 import 할 수 있습니다.
import { PersistedClient, Persister } from "@tanstack/react-query-persist-client";
indexed DB 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) => {
set(idbValidKey, client);
},
restoreClient: async () => {
return await get<PersistedClient>(idbValidKey);
},
removeClient: async () => {
await del(idbValidKey);
},
} as Persister;
}
Web Storage API 와 비교해서, Indexted DB가 더 빠르고, 5MB 만큼 더 저장할수 있고, serialization 도 안해도 됩니다. 즉 Date 나 File 같은 자바스크립트의 native type들을 더 쉽게 저장 할 수 있습니다.