new·Earn with mozg — 20% of every monthSend somebody here and take a fifth of every plan payment they make, for as long as they keep paying — not a bounty on the first invoice. Your handle is the link, the window is thirty days, and the commission lands on your balance the second they pay. Free to join: if you have signed in, you already have the link. mozg.sh/earnall news →
mozg.beta
Sign in

TanStack Query · React · all subjects

migration/v5

52 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

useInfiniteQuery now requires single object signature

useInfiniteQuery in v5 only supports the object format. The old multi-parameter signature useInfiniteQuery(key, fn, options) is no longer supported. You must use useInfiniteQuery({ queryKey, queryFn, ...options }).

useMutation now requires single object signature

useMutation in v5 only supports the object format. The old multi-parameter signature useMutation(fn, options) is no longer supported. You must use useMutation({ mutationFn, ...options }).

useIsFetching now requires object with queryKey

useIsFetching in v5 requires an object format with queryKey. The old signature useIsFetching(key, filters) is no longer supported. You must use useIsFetching({ queryKey, ...filters }).

useIsMutating now requires object with mutationKey

useIsMutating in v5 requires an object format with mutationKey. The old signature useIsMutating(key, filters) is no longer supported. You must use useIsMutating({ mutationKey, ...filters }).

QueryClient methods signature changes in v5

All QueryClient methods changed to require an object as the first parameter containing queryKey or mutationKey: isFetching({ queryKey, ...filters }), getQueriesData({ queryKey, ...filters }), setQueriesData({ queryKey, ...filters }, updater, options), removeQueries({ queryKey, ...filters }), resetQueries({ queryKey, ...filters }, options), cancelQueries({ queryKey, ...filters }, options), invalidateQueries({ queryKey, ...filters }, options), refetchQueries({ queryKey, ...filters }, options).

QueryCache methods signature changes in v5

QueryCache methods find() and findAll() now require an object parameter: find({ queryKey, ...filters }) and findAll({ queryKey, ...filters }).

queryClient.prefetchQuery is deprecated in v5

queryClient.prefetchQuery() is deprecated and will be removed in v6. Use queryClient.query({ queryKey: key, queryFn: fn, ...options }).catch(noop) instead.

queryClient.prefetchInfiniteQuery is deprecated in v5

queryClient.prefetchInfiniteQuery() is deprecated and will be removed in v6. Use queryClient.infiniteQuery({ queryKey: key, queryFn: fn, ...options }).catch(noop) instead.

queryClient.ensureInfiniteQueryData is deprecated in v5

queryClient.ensureInfiniteQueryData() is deprecated and will be removed in v6. Use queryClient.infiniteQuery({ queryKey: key, ...options, staleTime: 'static' }) instead.

queryClient.getQueryData now accepts only queryKey

queryClient.getQueryData() in v5 accepts only a queryKey parameter. The old signature queryClient.getQueryData(queryKey, filters) is no longer supported. Use queryClient.getQueryData(queryKey).

queryClient.getQueryState now accepts only queryKey

queryClient.getQueryState() in v5 accepts only a queryKey parameter. The old signature queryClient.getQueryState(queryKey, filters) is no longer supported. Use queryClient.getQueryState(queryKey).

Codemod for v5 breaking changes

A codemod is available to help migrate from v4 to v5. For .js or .jsx files run: npx jscodeshift@latest ./path/to/src/ --extensions=js,jsx --transform=./node_modules/@tanstack/react-query/build/codemods/src/v5/remove-overloads/remove-overloads.cjs. For .ts or .tsx files, use --extensions=ts,tsx --parser=tsx. Review generated code thoroughly, run prettier and eslint after, and check console logs for edge cases.

onSuccess, onError, onSettled callbacks removed from useQuery

useQuery no longer supports onSuccess, onError, and onSettled callbacks in v5. These callbacks have been removed from queries (but not mutations). Use alternatives as described in the RFC at https://github.com/TanStack/query/discussions/5279.

refetchInterval callback signature changed

The refetchInterval callback in v5 now only receives the query object, not data. Old signature: (data: TData | undefined, query: Query) => number | false | undefined. New signature: (query: Query) => number | false | undefined. Access data using query.state.data if needed.

useQuery.remove() method removed

The remove() method on the useQuery result has been removed. To remove a query, use queryClient.removeQueries({ queryKey: key }) instead.

Minimum TypeScript version is 4.7

TanStack Query v5 requires TypeScript 4.7 or later, mainly due to an important fix in type inference. See TypeScript issue #43371 for more information.

isDataEqual option removed

The isDataEqual option has been removed from useQuery in v5. Use structuralSharing with a function instead: structuralSharing: (oldData, newData) => customCheck(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData). Import replaceEqualDeep from @tanstack/react-query.

Custom logger removed

Custom loggers have been removed in v5. They were already deprecated in v4 and only had effect in development mode.

ECMAScript private class fields used in v5

TanStack Query v5 now uses ECMAScript Private class features for private fields and methods, making them truly private at runtime and not just in TypeScript.

cacheTime renamed to gcTime

The cacheTime option has been renamed to gcTime in v5 to more accurately reflect its purpose. gcTime refers to garbage collection time - the time after which unused query data is removed from the cache. Example: gcTime: 10 * MINUTE.

useErrorBoundary option renamed to throwOnError

The useErrorBoundary option has been renamed to throwOnError in v5 to be more framework-agnostic and accurately reflect its functionality.

Error is now default type instead of unknown

In v5, the default error type is now Error instead of unknown in TypeScript. If you need to throw something that isn't an Error, you must set the generic explicitly: useQuery<number, string>({ ... }).

eslint prefer-query-object-syntax rule removed

The eslint rule prefer-query-object-syntax has been removed in v5 since the object syntax is now the only supported format.

keepPreviousData removed in favor of placeholderData

The keepPreviousData option and isPreviousData flag have been removed in v5. Use placeholderData with a function instead. Import the keepPreviousData function from @tanstack/react-query and pass it as placeholderData: keepPreviousData. The function receives (previousData, previousQuery) as arguments.

Caveats when migrating from keepPreviousData to placeholderData

When migrating from keepPreviousData to placeholderData in v5: (1) placeholderData always puts you in success state, while keepPreviousData could be in error state. (2) placeholderData sets dataUpdatedAt to 0, while keepPreviousData preserved the previous timestamp. You can use useEffect to track dataUpdatedAt if needed.

Window focus refetch uses visibilitychange event only

Window focus refetching in v5 now uses the visibilitychange event exclusively instead of listening to the focus event. This is possible because v5 only supports browsers that support visibilitychange.

Network status no longer relies on navigator.onLine

Network status detection in v5 no longer uses navigator.onLine, which has issues in Chromium. Instead, the query starts with online: true and only listens to online and offline events. This reduces false negatives but may increase false positives in offline apps using service workers.

Custom context prop removed in favor of queryClient

The custom context prop has been removed from v5. Instead of passing context: customContext, pass a custom queryClient instance directly as the second argument: useQuery({ ... }, queryClient). This provides the same isolation for MicroFrontends but is framework-agnostic.

refetchPage removed in favor of maxPages

The refetchPage option for infinite queries has been removed in v5. Use the new maxPages option instead to limit the number of pages stored and refetched. This handles the same use cases without the related UI inconsistency issues.

Dehydrate API changes in v5

The dehydrate API has been simplified in v5. The boolean options dehydrateMutations and dehydrateQueries have been removed. Use function equivalents instead: shouldDehydrateQuery and shouldDehydrateMutation. To not dehydrate queries/mutations, pass () => false.

Infinite queries require initialPageParam

Infinite queries in v5 require an explicit initialPageParam option. This replaces the previous pattern of providing a default value to pageParam in the queryFn function signature. Example: useInfiniteQuery({ queryKey, queryFn: ({ pageParam }) => fetchSomething(pageParam), initialPageParam: 0, getNextPageParam: ... }).

Manual mode for infinite queries removed

Manual mode for infinite queries (passing pageParam to fetchNextPage or fetchPreviousPage) has been removed in v5. This means getNextPageParam is now required for infinite queries.

null now indicates no further page in infinite queries

In v5, returning null from getNextPageParam or getPreviousPageParam now indicates there is no further page available. Previously, only undefined was checked. The check is now widened to include null.

No retries on the server in v5

In v5, the retry option defaults to 0 on the server instead of 3. This applies to queries with suspense enabled that execute on the server (available since React 18).

Status loading changed to pending in v5

In v5, the status value 'loading' has been changed to 'pending'. The isLoading flag has been changed to isPending. A new derived isLoading flag now equals isPending && isFetching. This applies to both queries and mutations.

isInitialLoading deprecated in v5

In v5, isInitialLoading has been deprecated and renamed. The new isLoading flag is equivalent to isPending && isFetching, which represents the same concept. isInitialLoading will be removed in the next major version.

hashQueryKey renamed to hashKey in v5

The hashQueryKey function has been renamed to hashKey in v5 because it also hashes mutation keys and can be used in predicate functions of useIsMutating and useMutationState.

Minimum React version is 18.0

TanStack Query v5 requires React 18.0 or later. This is because v5 uses the useSyncExternalStore hook, which is only available in React 18.0 and later.

contextSharing prop removed from QueryClientProvider

The contextSharing prop has been removed from QueryClientProvider in v5. For sharing the same query client across multiple packages, pass a shared custom queryClient instance directly to the hooks instead of using context.

unstable_batchedUpdates no longer used automatically

v5 no longer automatically uses unstable_batchedUpdates as the batching function since it is a noop in React 18. If your framework supports a custom batching function, call notifyManager.setBatchNotifyFunction(batchFunction) to set it.

Hydrate component renamed to HydrationBoundary

In v5, the Hydrate component has been renamed to HydrationBoundary. The useHydrate hook has been removed. Example: <HydrationBoundary state={dehydratedState}><App /></HydrationBoundary>.

HydrationBoundary only hydrates queries

In v5, HydrationBoundary no longer hydrates mutations, only queries. To hydrate mutations, use the low level hydrate API or the persistQueryClient plugin.

Hydration timing changed for existing cache entries

In v5, new queries are hydrated in the render phase (SSR as usual), but queries already in the cache are hydrated in an effect if their data is fresher. This prevents premature updates on existing pages during page transitions in Server Components.

Query defaults merging behavior in v5

In v5, queryClient.getQueryDefaults merges all matching registrations instead of returning only the first one. Calls to queryClient.setQueryDefaults should be ordered with increasing specificity: from most generic key to least generic key.

Simplified optimistic updates in v5

v5 provides a simplified optimistic update approach using the returned variables from useMutation. When a mutation is pending (isPending: true), you can access addTodoMutation.variables to show optimistic UI changes without directly modifying the cache.

maxPages option for infinite queries

v5 introduces a maxPages option for infinite queries to limit the number of pages stored and refetched. This reduces memory consumption and improves refetch performance. The infinite list must be bi-directional (both getNextPageParam and getPreviousPageParam required).

combine option for useQueries

v5 introduces a new combine option for useQueries. See the useQueries documentation for details on how to use this feature.

Experimental fine-grained storage persister

v5 includes an experimental fine-grained storage persister available as experimental_createPersister. See the plugin documentation for more details.

Typesafe query options in v5

v5 provides a typesafe way to create query options. See the TypeScript documentation for details on typing query options.

useSuspenseQuery hook in v5

v5 introduces a dedicated useSuspenseQuery hook for suspense. The data property will never be undefined at the type level. Example: const { data: post } = useSuspenseQuery({ queryKey: ['post', postId], queryFn: () => fetchPost(postId) }). The experimental suspense: boolean flag has been removed.

useSuspenseQueries hook in v5

v5 introduces a dedicated useSuspenseQueries hook for multiple queries with suspense. This replaces the experimental suspense: boolean flag from earlier versions.

prefetchQuery and ensureQueryData are deprecated

The prefetchQuery and ensureQueryData methods are deprecated and will be removed in the next major version of TanStack Query. Use the query method instead for prefetching.

Give your agent this brain

migration/v5 — TanStack Query · React