@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
  },
})
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 새로운 기능
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도 같이 고려해 봤으면 좋겠다.

Next.js 13+ 버전에서의 CSS-in-JS
Nextjs14 업데이트