This episode covers the latest stable features of TanStack Query v5.x: the keyed-object API, useSuspenseQuery, structural sharing, default retry, React 19 support, the v5.101.x release in July 2026, and the development direction toward Query v6.

TanStack Query v5 was released in October 2023 and has been continuously updated throughout 2024 to 2026. Each minor release brings small refinements: eslint-plugin-query fixes, dependency refreshes, and adjustments to the fast-moving ecosystem like React 19.
Episode 20 summarizes the features that make v5 stable and pleasant to use: the uniform keyed-object API, first-class useSuspenseQuery, structural sharing, default retry, and queryOptions for shareable query definitions. Finally, you see the v5.101.x release map and the latest news about Query v6.
The biggest change in v5 was the removal of all overloads. useQuery now always accepts one object with queryKey and queryFn properties — no more two calling forms like in v4:
import { useQuery } from "@tanstack/react-query"
const { data, isPending, error } = useQuery({
queryKey: ["todos", id],
queryFn: () => fetchTodoById(id),
staleTime: 30 * 1000,
})In v4, you could write useQuery(["todos"], fetchTodos) with two separate arguments. In v5, one object is the only way. queryKey and queryFn are always required, while options like staleTime and gcTime are optional properties of the same object. This uniformity makes TypeScript produce much clearer error messages.
Because the call always goes through an object, you can extract a query definition into one place with queryOptions. This definition is type-safe and can be reused by useQuery, prefetchQuery, and getQueryData:
import { queryOptions } from "@tanstack/react-query"
export const todosOptions = queryOptions({
queryKey: ["todos"],
queryFn: fetchTodos,
staleTime: 5 * 60 * 1000,
})
export async function prefetchTodos(client) {
return client.prefetchQuery(todosOptions)
}queryOptions creates a single source of truth for the query key and query function. You don't need to rewrite queryKey: ["todos"] in both the hook and the prefetch — just import todosOptions. This is a highly recommended pattern for team-scale applications (discussed in detail in episode 21).
Suspense support in v4 was still experimental; in v5 it became a first-class feature with the dedicated useSuspenseQuery hook. Unlike useQuery, this hook doesn't return isPending — the component is suspended directly until the data is ready:
import { Suspense } from "react"
import { useSuspenseQuery } from "@tanstack/react-query"
function TodosList() {
const { data } = useSuspenseQuery({
queryKey: ["todos"],
queryFn: fetchTodos,
})
return <ul>{data.map((todo) => <li key={todo.id}>{todo.title}</li>)}</ul>
}
function App() {
return (
<Suspense fallback={<p>Memuat data...</p>}>
<TodosList />
</Suspense>
)
}useSuspenseQuery eliminates manual loading branches. When the data doesn't exist yet, React throws to the nearest Suspense boundary; when the data arrives, the component renders with data that is guaranteed to be available. There is no empty state to check.
structuralSharing in v5 remains active by default. When queryFn returns new data, TanStack Query compares the old and new structures, then preserves references to unchanged parts. The effect: memoized components don't need to re-render for identical data, and useMemo depending on object references stays stable. This is one of the reasons v5 feels responsive without extra tuning.
At the time of writing this episode, the latest stable release is v5.101.4 (July 2026). You can verify it directly from the npm registry:
npm view @tanstack/react-query version
npm view @tanstack/react-query-devtools version
npm i @tanstack/react-query@latestThe v5.101.x series contains fixes for @tanstack/eslint-plugin-query, dependency refreshes, and React 19 support adjustments. The eslint-plugin-query package is installed as a dev dependency and wired into the ESLint flat config:
npm i -D @tanstack/eslint-plugin-queryimport query from "@tanstack/eslint-plugin-query"
export default [
...query.configs["flat/recommended"],
{
rules: {
"@tanstack/query/stable-query-client": "error",
"@tanstack/query/exhaustive-deps": "error",
},
},
]The stable-query-client rule ensures QueryClient isn't recreated inside a component, and exhaustive-deps ensures all dependencies are included in the query key. Both catch the most common caching bugs before they reach code review.
Two built-in behaviors worth remembering: the default retry in v5 is 3 times with exponential backoff delays, and the default gcTime is 5 minutes. For React 19 applications, v5 supports Concurrent Rendering and Suspense integration well, including useSuspenseQuery, which takes advantage of server streaming features in the Next.js App Router.
After v5 has been stable for years, development has already moved toward the next generation. Query v6 is still in development; one of the most visible markers is the solid-query@6.0.0-beta package, which has started shipping as a beta. This beta release gives a glimpse of the v6 API without changing the stable v5 behavior in the main ecosystem.
For those just starting out, there's no need to wait for v6. v5.101.x is a stable release, fully documented, and used in production around the world. The v5 capabilities already cover everything discussed from episodes 0 to 19. Migrating to v6 later, if needed, will follow patterns you've already mastered.
Tip
Always check the changelog on the TanStack/query GitHub before a major upgrade. Default behaviors like retry and gcTime can change between versions, and those changes rarely require a big rewrite if you're already using clean query keys.
Episode 20 closed the version knowledge gap: the keyed-object API and queryOptions make query definitions uniform and shareable, useSuspenseQuery simplifies loading, and the v5.101.x release brought eslint-plugin-query improvements and mature React 19 support.
Key takeaways:
useQuery in v5 always accepts one object with queryKey and queryFn.queryOptions unifies query definitions for hooks, prefetch, and cache.useSuspenseQuery eliminates manual loading states.structuralSharing is active by default and preserves data references.retry is 3 times with exponential backoff.In the next episode, episode 21, we will discuss production-ready architecture — query module folder structure, query key catalogs, domain-specific custom hooks, monitoring, bundle size, SSR tuning, and caching and invalidation runbooks for team scale.