Next action:
[React Query] useQuery 동작원리(1)
function useQuery (
queryKey: QueryKey,
queryFn: QueryFunction,
options?: UseQueryOptions
): UseQueryResult
--------------------------------------------------------------------
--------------------------------------------------------------------
// 1. useQuery 호출
const result = useQuery(['todos'], fetchTodos)
// 2. 내부적으로 Query 인스턴스 생성
const query = new Query({
queryKey: ['todos'],
queryFn: fetchTodos,
...options
})
// 3. QueryCache에 쿼리 추가
queryClient.getQueryCache().add(query)
core에는 핵심 객체 4개가 아주 중요하다
QueryClient , QueryCache, Query, QueryObserver
// _app.tsx
import { QueryClient } from '@tanstack/query-core';
import { QueryClientProvider } from '@tanstack/react-query';
import type { AppProps } from 'next/app';
export default function App({ Component, pageProps }: AppProps) {
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
</QueryClientProvider>
);
}
QueryClient
QueryCache 객체를 가지고있음.QueryCache
Query 객체들을 저장함.Query 객체가 저장됨export class QueryCache extends Subscribable<QueryCacheListener>{
config: QueryCacheConfig
private queries: Query<any, any, any, any>[]
private queriesMap: QueryHashMap
add(query: Query<any, any, any, any>): void {
if (!this.queriesMap[query.queryHash]) {
this.queriesMap[query.queryHash] = query
this.queries.push(query)
this.notify({
type: 'added',
query,
})
}
}
}
Query
QueryCache와 자신의 상태가 변경되었을때 호출할 옵저버들을 가짐QueryObserver
export class QueryObserver<...> extends Subscribable<QueryObserverListener<TData, TError>> {
...
constructor(
client: QueryClient,
options: QueryObserverOptions<...>
) {
super()
this.client = client
...
this.trackedProps = new Set()
...
}
...
protected onSubscribe(): void {
if (this.listeners.length === 1) {
this.currentQuery.addObserver(this)
if (shouldFetchOnMount(this.currentQuery, this.options)) {
this.executeFetch()
}
...
}
}
...
private updateQuery(): void {
const query = this.client.getQueryCache().build(this.client, this.options)
if (query === this.currentQuery) {
return
}
this.currentQuery = query
...
}
}