Replies: 17 comments 8 replies
-
extra. pre apollo-client vs react-query useQuery 형태의 사용은 무엇이 먼저?
결론적으로, ChatGPT said 아폴로 먼저~ 그래서 익숙했구먼 react-query 살펴보기
react-query 구현에서 궁금한점
첫 뜯어보기overloading많은 라이브러리 들이 함수 오버로딩을 하는데 이번에도 발견 한번 정리하고 가면 좋을듯. function len(s: string): number;
function len(arr: any[]): number;
function len(x: any) {
return x.length;
}
상태의 변화 감지와 업데이트useSyncExternalStore리액트 외부 저장소의 값의 변화를 연동해서 리액트 컴포넌트를 리렌더링 시키기위한 API라고 생각하면됨.
결국 내부 상태를 두고. |
Beta Was this translation helpful? Give feedback.
-
|
왜 @tanstack/query-core 못 찾는 거야 useQuery->useBaseQuery
|
Beta Was this translation helpful? Give feedback.
-
nx graphCody를 활용해 1차 분석해보기Code Structure
Cody 초기 답변이 미흡해서 이것저것 질문해보았습니다 (정리는 담주에 공유할게욥). |
Beta Was this translation helpful? Give feedback.
-
Error handling
|
Beta Was this translation helpful? Give feedback.
-
[번외] TanStack Query 개발자도구 정말 좋네요.쿼리 키들을 볼 수 있고요, 특히 액션 버튼들이 유용하네요. Refetch, 로딩 상태로 변환, 에러 상태로 변환할 수가 있고요. 제 개발 습관으로는 콘솔에 로깅하는 것과 로딩과 에러 처리를 위해서 코드 주석먹이고 분기 처리하는 것들, 그리고 크롬 개발자도구의 네트워크탭을 두리번거리는 횟수를 줄여줄 것 같아요. 깔끔하게 fetch만 정리해서 보여줘서 데이터 읽는 시간도 아낄 수 있고요. |
Beta Was this translation helpful? Give feedback.
-
TanStack Query는 어떻게 탄생하게 되었을까?상태관리 라이브러리가 많은데 이걸 쓰더라도 비동기로 오는 데이터, 서버 데이터에 맞추어 동작하기에는 항상 어려움이 따른다. 본질적으로 서버의 데이터 상태는 프론트엔드에서 데이터를 처리하는 것과 완전히 다르기 때문이다. 서버의 데이터는,
이걸 다 처리해서 가져왔다고 해도 프론트엔드 자체에서 난관에 봉착하게 되는데,
이러한 문제를 해결하기 위해서 등장한 라이브러리이다. 캐싱이 어려운 이유다음과 같은 이유로 성능 향상과 사용자 경험 개선을 동시에 달성하는 것이 어렵다.
|
Beta Was this translation helpful? Give feedback.
-
TanStack의 기본동작과 쿼리, 쿼리 키, 쿼리 함수사용법을 모르고 코드를 읽으면 잘 이해가 안되니까~ 기본 내용만 정리한다. 기본동작 (설정 변경 가능)
쿼리 키
쿼리 함수
|
Beta Was this translation helpful? Give feedback.
-
useQuery 코드 보기
노트
|
Beta Was this translation helpful? Give feedback.
-
|
목표 : 오늘은 캐시 스토어를 중점적으로 다뤄봄 캐싱의 핵심은 다음 셋
TanStack Query의 캐싱 로직은 QueryClient역할 : 쿼리 인스턴스를 생성하고 관리하며, 캐시 상태를 유지
export function useSyncExternalStore<Snapshot>(
subscribe: (onStoreChange: () => void) => () => void,
getSnapshot: () => Snapshot,
getServerSnapshot?: () => Snapshot,
): Snapshot;QueryObserver
QueryCachereact-query 는 key를 어떻게 hash 화 할까? 👀key hash화 로직 발견! 🎉 이렇게 얻은 hash를 가지고 캐시 객체에 있는지 검사해본다. QueryStore쿼리 스토어는 이런 인터페이스를 가진 맵으로 캐시 객체에 쿼리가 없으면 새로 만든다. Query 는 다양한 내부 멤버를 가지고 있는데 GPTs CodeCopilot의 설명
중요한 멤버 변수 및 메소드 설명1.
|
Beta Was this translation helpful? Give feedback.
-
2. Deep Dive In Caching
TL;DR
BackgroundThe caching mechanism that React Query usesWhen does React Query ask the backend again for new data?Every time a component that calls
Deep dive in React Query caching mechanism with architectureQueryClient
// @tanstack/query-core/src/queryClient.ts
class QueryClient {
#queryCache: QueryCache
#mutationCache: MutationCache
constructor(config: QueryClientConfig = {}) {
this.#queryCache = config.queryCache || new QueryCache()
this.#mutationCache = config.mutationCache || new MutationCache()
...
}
...
}QueryCache
class QueryCache extends Subscribable<QueryCacheListener> {
#queries: QueryStore
constructor(public config: QueryCacheConfig = {}) {
super()
this.#queries = new Map<string, Query>()
}
}
export interface QueryStore {
has: (queryHash: string) => boolean
set: (queryHash: string, query: Query) => void
get: (queryHash: string) => Query | undefined
delete: (queryHash: string) => void
values: () => IterableIterator<Query>
}
class QueryCache extends Subscribable<QueryCacheListener> {
...
get<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
>(
queryHash: string,
): Query<TQueryFnData, TError, TData, TQueryKey> | undefined {
return this.#queries.get(queryHash) as
| Query<TQueryFnData, TError, TData, TQueryKey>
| undefined
}
}
/**
* Default query & mutation keys hash function.
* Hashes the value into a stable hash.
*/
export function hashKey(queryKey: QueryKey | MutationKey): string {
return JSON.stringify(queryKey, (_, val) =>
isPlainObject(val)
? Object.keys(val)
.sort()
.reduce((result, key) => {
result[key] = val[key]
return result
}, {} as any)
: val,
)
}QueryThis class represents a single query in the system. It contains the logic for fetching data, as well as the current state of the query (including the data itself, any error that occurred, and loading status). It also handles caching and updating the data.
class Query<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> extends Removable {
queryKey: TQueryKey
queryHash: string
options!: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
state: QueryState<TData, TError>
isFetchingOptimistic?: boolean
#initialState: QueryState<TData, TError>
#revertState?: QueryState<TData, TError>
#cache: QueryCache
#retryer?: Retryer<TData>
observers: Array<QueryObserver<any, any, any, any, any>>
#defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
#abortSignalConsumed: boolean
...
}
// @tanstack/query-core/src/query.ts
notifyManager.batch(() => {
this.observers.forEach((observer) => {
observer.onQueryUpdate()
})
this.#cache.notify({ query: this, type: 'updated', action })QueryObserverThis class is used to subscribe to a
class QueryObserver<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> extends Subscribable<QueryObserverListener<TData, TError>> {
#client: QueryClient
#currentQuery: Query<TQueryFnData, TError, TQueryData, TQueryKey> = undefined!
#currentQueryInitialState: QueryState<TQueryData, TError> = undefined!
#currentResult: QueryObserverResult<TData, TError> = undefined!
#currentResultState?: QueryState<TQueryData, TError>
#currentResultOptions?: QueryObserverOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey
>
...
}
References |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
리액트 쿼리식 사고
|
Beta Was this translation helpful? Give feedback.
-
리액트 쿼리로 웹소켓 연결하기
|
Beta Was this translation helpful? Give feedback.
-
3. Seeding the Query CacheWhat is "Seeding"?In the context of caching, seeding refers to the process of pre-populating the cache with data before it is actually requested by the application or users to improve the cache's performance and reduce the cache miss rate. Approaches to seed the cache
Pull approachIn the pull approach, the cache is populated on-demand when a query is executed. You can use the const useTodo = (id: number) => {
const queryClient = useQueryClient()
return useQuery({
queryKey: ['todos', 'detail', id],
queryFn: () => fetchTodo(id),
initialData: () => {
// ⬇️ look up the list cache for the item
return queryClient
.getQueryData(['todos', 'list'])
?.find((todo) => todo.id === id)
},
})
}Note that const useTodo = (id: number) => {
const queryClient = useQueryClient()
return useQuery({
queryKey: ['todos', 'detail', id],
queryFn: () => fetchTodo(id),
initialData: () => {
// ⬇️ look up the list cache for the item
return queryClient
.getQueryData(['todos', 'list'])
?.find((todo) => todo.id === id)
},
initialDataUpdatedAt: () =>
// ⬇️ get the last fetch time of the list
queryClient.getQueryState(['todos', 'list'])?.dataUpdatedAt,
})
}Push approachAlternatively, you can manually place the detail cache whenever you fetch the list query. Use const useTodos = () => {
const queryClient = useQueryClient()
return useQuery({
queryKey: ['todos', 'list'],
queryFn: async () => {
const todos = await fetchTodos()
todos.forEach((todo) => {
// ⬇️ create a detail cache for each item
queryClient.setQueryData(['todos', 'detail', todo.id], todo)
})
return todos
},
})
}This has the advantage that the staleness is automatically measured. However, the cached data might no longer be available once the user actually navigates to the detail view. Moreover, if tour list is too long, too many unnecessary cache entries might be created. |
Beta Was this translation helpful? Give feedback.
-
Client state vs Server State서버 상태는 백엔드로부터 받아온 데이터를 클라이언트에서 관리하고 있을 때 React Query Tanner Linsley가 Apollo 의 장점을 채용하여 REST API 로 가져옴 캐시에 대한 gc 를 두는 것도 재밌음. 사용자가 컨트롤할 수 있다는 것도. Don't use the queryCache as a local state manager! |
Beta Was this translation helpful? Give feedback.
-
|
#10: React Query as a State Manager Async state manager
A data sync tool백엔드 데이터와 동기화 수단 제공 Stale while Revalidate오래된 데이터라도 일단 리턴하고 백그라운드에서 다시 불러오기 Smart refetches컴포넌트가 마운트 될때, 윈도우가 포커스될때, 네트워크가 재연결될 때 등 자주 사용하는 트리거를 빌트인 옵션으로 제공 custom staleTime키마다 staleTime 을 다르게 둘 수 있음.
|
Beta Was this translation helpful? Give feedback.
-
피드백
오픈 소스 분석 체크리스트
다음주는 어떻게 할까요?dayjs 로 결정! |
Beta Was this translation helpful? Give feedback.











Uh oh!
There was an error while loading. Please reload this page.
-
react-query의 useQuery 함수부터 읽어봅니다.
Beta Was this translation helpful? Give feedback.
All reactions