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()
가 호출되고 캐시가 즉시 삭제됩니다.persistQueryClientSave
dehydrated
상태가 되고 저장됩니다. 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 persistQueryClient
persistQueryClient
는 캐시 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?: () => void
PersistQueryClientProvider
를 사용하고 싶으면, 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들을 더 쉽게 저장 할 수 있습니다.