@tanstack/react-query 5 업데이트, 변경사항
2023-11-06, (월) 10:46
@tanstack/react-query v5 변경사항 (마이그레이션)
typescript
- useQuery(key, fn, options) // 이렇게도 쓸수 있었다면
+ useQuery({ queryKey, queryFn, ...options }) // 이제는 이렇게만 쓸수 있다
- useInfiniteQuery(key, fn, options)
+ useInfiniteQuery({ queryKey, queryFn, ...options })
- useMutation(fn, options)
+ useMutation({ mutationFn, ...options })
- useIsFetching(key, filters)
+ useIsFetching({ queryKey, ...filters })
- useIsMutating(key, filters)
+ useIsMutating({ mutationKey, ...filters })
- queryClient.isFetching(key, filters)
+ queryClient.isFetching({ queryKey, ...filters })
- queryClient.ensureQueryData(key, filters)
+ queryClient.ensureQueryData({ queryKey, ...filters })
- queryClient.getQueriesData(key, filters)
+ queryClient.getQueriesData({ queryKey, ...filters })
- queryClient.setQueriesData(key, updater, filters, options)
+ queryClient.setQueriesData({ queryKey, ...filters }, updater, options)
- queryClient.removeQueries(key, filters)
+ queryClient.removeQueries({ queryKey, ...filters })
- queryClient.resetQueries(key, filters, options)
+ queryClient.resetQueries({ queryKey, ...filters }, options)
- queryClient.cancelQueries(key, filters, options)
+ queryClient.cancelQueries({ queryKey, ...filters }, options)
- queryClient.invalidateQueries(key, filters, options)
+ queryClient.invalidateQueries({ queryKey, ...filters }, options)
- queryClient.refetchQueries(key, filters, options)
+ queryClient.refetchQueries({ queryKey, ...filters }, options)
- queryClient.fetchQuery(key, fn, options)
+ queryClient.fetchQuery({ queryKey, queryFn, ...options })
- queryClient.prefetchQuery(key, fn, options)
+ queryClient.prefetchQuery({ queryKey, queryFn, ...options })
- queryClient.fetchInfiniteQuery(key, fn, options)
+ queryClient.fetchInfiniteQuery({ queryKey, queryFn, ...options })
- queryClient.prefetchInfiniteQuery(key, fn, options)
+ queryClient.prefetchInfiniteQuery({ queryKey, queryFn, ...options })
- queryCache.find(key, filters)
+ queryCache.find({ queryKey, ...filters })
- queryCache.findAll(key, filters)
+ queryCache.findAll({ queryKey, ...filters })
- queryClient.getQueryData 및 queryClient.getQueryState가 queryKey 인수 하나만 허용.
typescript
- queryClient.getQueryData(queryKey, filters)
+ queryClient.getQueryData(queryKey)
- queryClient.getQueryState(queryKey, filters)
+ queryClient.getQueryState(queryKey)
-
useQuery에서 콜백 제거 (onSuccess, onError, onSettled)
-
refetchInterval의 콜백에는 query만 전달
typescript
- refetchInterval: number | false | ((data: TData | undefined, query: Query) => number | false | undefined)
+ refetchInterval: number | false | ((query: Query) => number | false | undefined)
- useQuery에 remove메소드 제거, queryClient.removeQueries로 동일한 기능 가능
typescript
const queryClient = useQueryClient();
const query = useQuery({ queryKey, queryFn });
- query.remove()
+ queryClient.removeQueries({ queryKey })
- typescript최소 버전은 4.7
- useQuery에서 isDataEqual 제거, structuralSharing으로 동일한 기능 구현 가능
typescript
import { replaceEqualDeep } from '@tanstack/react-query'
- isDataEqual: (oldData, newData) => customCheck(oldData, newData)
+ structuralSharing: (oldData, newData) => customCheck(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData)
- custom logger 제거됨
- 지원되는 브라우저 변경
shell
Chrome >= 91
Firefox >= 90
Edge >= 91
Safari >= 15
iOS >= 15
opera >= 77
- private이 TypeScript에서 ECMAScript 클래스 기능으로 변경됨. 진정한 의미의 privated이 되었으므로, 런타임 밖에서 접근할 수 없다.
- cacheTime 에서 gcTime으로 변경
typescript
const MINUTE = 1000 * 60;
const queryClient = new QueryClient({
defaultOptions: {
queries: {
- cacheTime: 10 * MINUTE,
+ gcTime: 10 * MINUTE,
},
},
})
- useErrorBoundary옵션 이름 변경 throwOnError
- 에러 타입이 unknown에서 Error로 변경
- generic에 에러 타입 지정 가능
typescript
useQuery<number, string>({
queryKey: ['some-query'],
queryFn: async () => {
if (Math.random() > 0.5) {
throw 'some error'
}
return 42
},
})
- keepPreviousData 는 placeholderData에 통합
- custom
context
는 제거됨, 대신 queryClient 인스턴스 사용
typescript
import { queryClient } from './my-client'
const { data } = useQuery(
{
queryKey: ['users', id],
queryFn: () => fetch(...),
- context: customContext
},
+ queryClient,
)
- refetchPage제거, 대신 maxPages (무한 쿼리에서)
- 새로운 dehydrate API (단순화), 기존의 dehydrateMutations 및 dehydrateQueries 옵션 제거됨, 같은 기능을 수행하려면 shouldDehydrateQuery또는 shouldDehydrateMutation를 사용해야하며, 모든 동작을 수행하지 않으려면
() => false
- 이제 useInfiniteQuery 무한 쿼리에 initialPageParam이 필요합니다.
typescript
useInfiniteQuery({
queryKey,
- queryFn: ({ pageParam = 0 }) => fetchSomething(pageParam),
+ queryFn: ({ pageParam }) => fetchSomething(pageParam),
+ initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.next,
})
- Manual mode에서 무한쿼리는 제거됨, 더이상 pageParams을 덮어써서 무한쿼리인것처럼 사용할 수 없다.
- getNextPageParam 또는 getPreviousPageParam에 null을 반환해도 다음페이지가 없음을 확인함.
- 서버 retry기본값이 3에서 0으로 변경, React 18부터는 서스펜스(suspense)가 활성화된 쿼리도 서버에서 바로 실행될 수 있게 됐으므로 서버에서는 재시도를 하지 않도록 기본값이 변경됨.
- status의 loading은 pending으로 변경
- hasgQueryKey는 hashKey로 변경
- React최소 버전은 18.0버전
- QueryClientProvider에서 contextSharing제거
- Hydration API 변경사항, Hydrate가 HydrationBoundary로 변경되고 useHydrate훅은 제거됨. HydrationBoundary는 더이상 뮤테이션을 수행하지 않으므로, hydrate 뮤테이션을 수행하려면 hydrate API를 이용하거나, persistQueryClient 플러그인을 사용
typescript
- import { Hydrate } from '@tanstack/react-query'
+ import { HydrationBoundary } from '@tanstack/react-query'
- <Hydrate state={dehydratedState}>
+ <HydrationBoundary state={dehydratedState}>
<App />
- </Hydrate>
+ </HydrationBoundary>
@tanstack/react-query v5 새로운 기능
- 단순화된 Optimistic 업데이트
- 무한 쿼리에서 maxPages 옵션으로 페이지 수를 제한하여 성능향상을 꾀했다. 그러나 무한 쿼리는 양방향이어야 한다 (getNextPageParam과 getPreviousPageParam 둘다 정의되어야 함.)
- 무한쿼리는 pages옵션을 사용하면 여러페이지를 prefetch할 수 있다.
- useQueries에 combine옵션 추가됨
- suspense후크 추가(stable), 이를 활용하면, 데이터가 undefined가 되지 않기에 타입 안정성이 더욱 높아졌다.
typescript
const { data: post } = useSuspenseQuery({
// ^? const post: Post
queryKey: ['post', postId],
queryFn: () => fetchPost(postId),
})
@tanstack/react-query v5
포트폴리오 작성 중에 이전 코드를 업데이트 하다 보니, react-query가 업데이트 되었단 사실을 알게 되었다.
@tanstack/react-query는 React 앱에서 비동기 데이터를 효율적으로 가져오고, 캐시하고, 동기화하는 데 도움을 주는 라이브러리다.
이제 막 배우는 단계인 사람들이 react-query를 무작정 사용하는 것을 권장하지 않는다. react-query를 쓰면, Nextjs가 그러하듯, 많은 문제 상황들을 큰 고민없이 해결 할 수있게한다. 그게 문제다. 기초단계의 개발자들은 그저 동작하는 결과만 보고 넘어간다. 왜 이걸 쓰는지 어떻게 동작하는지에 대한 깊은 의문을 가지지 어렵게 된다.
추가로, 만약 Next.js 14 버전을 쓴다면, 캐싱 관리는 Nextjs가 확장한 fetch나 Server action등으로도 해결이 가능해졌다.
Nextjs에서 react-query를 쓰길 고려했다면, swr도 같이 고려해 봤으면 좋겠다.