Skip to content
Tien Nguyen logo Tien Nguyen
Back to blog

React Query vs Redux: the wrong question, and the right one

Tien Nguyen

Tien Nguyen

· 9 min read

React Query vs Redux: the wrong question, and the right one
Frontend craftReact

Here’s the honest answer to “React Query vs Redux”: it’s the wrong question, because they don’t manage the same kind of state. React Query manages server state, the data you fetch from an API and cache. Redux manages client state, the synchronous app state you own. Pitting them against each other is like asking whether a fridge is better than a pantry.

So the real questions, and their answers up front: for server data, use React Query (or RTK Query), not Redux. For client state, use useState, Context, or a light store, and reach for Redux only when that state gets large and complex. The actual apples-to-apples comparison is React Query vs RTK Query. And in 2026 there’s a twist worth naming: your AI assistant still writes the outdated pattern, Redux slices that fetch and cache server data, which is exactly the job React Query exists to take off your hands. I build on both, and I’ve pulled this exact fetch-and-cache slice out of more than one codebase, so this is a lived-in read.

Why React Query vs Redux is the wrong question

The two tools sit in different categories, and once you see it the “vs” mostly dissolves.

React Query owns server state. That is data that lives on a server, that you don’t own, and that can change without you: API responses, a cache you keep in sync. One hook fetches it, caches it, refetches it in the background, and hands you loading and error states:

React Query: server state (data you fetch and cache)
const { data: projects, isPending } = useQuery({
queryKey: ['projects'],
queryFn: () => fetch('/api/projects').then((r) => r.json()),
});

Redux owns client state. That is synchronous state your app fully controls: which modal is open, the current theme, a multi-step form’s progress:

Redux Toolkit: client state (app state you own)
const uiSlice = createSlice({
name: 'ui',
initialState: { sidebarOpen: false, theme: 'dark' },
reducers: {
toggleSidebar: (s) => { s.sidebarOpen = !s.sidebarOpen; },
},
});

Different jobs. They coexist in the same app with zero conflict. The reason “React Query vs Redux” feels like a matchup at all is historical: before React Query, people used Redux for both, so server data ended up in Redux by default.

Which tool for which state?

Here is the decision the comparison articles dance around, made into a rule you can actually apply.

Decision guide: server state (data from an API you fetch and cache, that changes without you) goes to React Query or RTK Query; client state (UI toggles, form drafts, theme, that you own and is synchronous) goes to useState, Context, or Zustand, with Redux only for large complex shared client state

Ask one question about each piece of state: do I own it, or does a server?

  • A server owns it (it came from an API, it can go stale, other users can change it): that is server state. Use React Query or RTK Query. Do not put it in Redux.
  • You own it (UI state, form input, session flags): that is client state. Start with useState or Context. Reach for a store (Zustand, or Redux) when it is shared widely and gets complex.

Most of what teams used to keep in a global Redux store was actually server state. Move that to React Query and the amount of Redux you need often collapses to a handful of genuinely client-side things.

React Query vs RTK Query: what’s the actual difference?

If you want a true head-to-head, the real one is React Query vs RTK Query, not React Query vs Redux, because RTK Query is Redux Toolkit’s own built-in data-fetching and caching layer. Both do server state; they just differ on where the cache lives and what else you’re using.

  • RTK Query ships inside Redux Toolkit and stores its cache in your Redux store. If you are already on Redux, it is the natural choice, nothing new to add.
  • React Query (TanStack Query v5) is standalone and library-agnostic, with the larger ecosystem and mindshare. If you are not committed to Redux, it is the common pick.

Either way you get caching, background refetching, and dedup. So when someone frames it as “Redux vs React Query,” the accurate response is that Redux’s answer to React Query is RTK Query, and that is the comparison to make.

What about writes? Mutations

Reads are only half of server state. Writes (creating a project, updating one, deleting one) are the other half, and React Query handles those too, with useMutation:

React Query: a write, with useMutation
const queryClient = useQueryClient();
const addProject = useMutation({
mutationFn: (name) =>
fetch('/api/projects', { method: 'POST', body: JSON.stringify({ name }) }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['projects'] }),
});

After a successful write, invalidateQueries marks the cached projects stale and React Query refetches them, so the UI stays in sync with no manual bookkeeping. RTK Query does the same with mutation endpoints and tag invalidation. Either way, the write, the cache update, and the refetch all live in your server-state library. A Redux thunk that POSTs and then hand-patches the store is the same anti-pattern as the read version: one more slice you don’t need.

Do you still need Redux in 2026?

Less than you used to, and that is the honest headline, not “Redux is dead.” Redux Toolkit (v2) is still a strong, standard option for large apps with complex, widely-shared client state. What shrank is its role: it is no longer the default home for server data, because a cache library does that job better.

For the client state that is left, you often don’t need Redux at all. useState and Context cover a lot, and a light store like Zustand covers most of the rest with far less ceremony. That is a separate comparison, one I make in Zustand vs Redux; the short version is to pick Redux when the client state is genuinely big and complex, and something lighter when it isn’t.

Why does AI still write Redux for server data?

This is the part no comparison mentions, and it is where the wrong question costs you real code. Ask an AI assistant to “load projects into the store” and you’ll often get the 2019 pattern: a thunk and a slice to fetch and cache server data by hand.

the pattern AI still writes: server data hand-managed in Redux
const fetchProjects = createAsyncThunk('projects/fetch', () =>
fetch('/api/projects').then((r) => r.json()),
);
const projectsSlice = createSlice({
name: 'projects',
initialState: { items: [], loading: false, error: null },
reducers: {},
extraReducers: (b) => {
b.addCase(fetchProjects.pending, (s) => { s.loading = true; });
b.addCase(fetchProjects.fulfilled, (s, a) => { s.items = a.payload; s.loading = false; });
b.addCase(fetchProjects.rejected, (s, a) => { s.error = a.error; s.loading = false; });
},
});
// ...plus dispatching fetchProjects() from a useEffect, and no caching, refetch, or dedup

It runs, so it looks right. But you just hand-wrote loading flags, error handling, and a store slot for data that a server owns, and you still don’t have caching, background refetching, or request deduplication. The whole thing collapses into the hook from earlier:

what it should be: React Query owns the server data
const { data: projects, isPending } = useQuery({
queryKey: ['projects'],
queryFn: () => fetch('/api/projects').then((r) => r.json()),
});

If you know server state is a different category, you catch this in review and delete the slice. If you don’t, you ship and maintain boilerplate the framework was built to erase. It is the same reason understanding the fundamentals matters more when AI writes the code: the AI reproduces the common old pattern, and you need to know why it’s wrong.

React Query vs Redux at a glance

React QueryRedux (Toolkit)
ManagesServer state (async cache)Client state (sync app state)
Best forAPI data: fetch, cache, syncUI, session, complex shared state
Caching / refetchBuilt inYou build it (or use RTK Query)
Server-data comparisonvs RTK QueryRTK Query is its data layer
Current versionTanStack Query v5Redux Toolkit v2
Need both?Common and healthyFor the client state that’s left

The takeaway

React Query vs Redux is a category error. React Query manages the state a server owns; Redux manages the state you own. Use React Query (or RTK Query) for server data, keep client state in useState, Context, or a light store, and bring in Redux only when that client state is genuinely large and complex.

The one rule that untangles all of it: ask whether a server owns the data. If it does, that is not Redux’s job, and it never really was. The clearest sign you’ve internalized that is the moment you delete a Redux slice an AI wrote to fetch an API, and replace the whole thing with one useQuery.

Frequently asked questions

Is Redux still used in 2026?

Yes, but for less. Redux Toolkit (now v2) is still a solid, standard choice for complex, shared client state in large apps. What changed is that most apps no longer use it for server data. A server-cache library like React Query or RTK Query handles fetching and caching far better than hand-written slices and thunks, so the amount of Redux a typical app needs has shrunk. Redux is not obsolete; it just does a smaller, more specific job now.

Do I need Redux with React Query?

Often not. React Query already owns your server state (the data you fetch and cache), which is what most global state used to be. What is left is client state: UI toggles, form drafts, the current theme. That is frequently small enough for useState, Context, or a light store like Zustand. Reach for Redux when the remaining client state is genuinely large, shared across many components, and complex. Plenty of apps run React Query with no Redux at all.

What is the difference between React Query and RTK Query?

They solve the same problem: server state (fetching, caching, refetching). React Query (TanStack Query) is standalone and library-agnostic. RTK Query is the same idea built into Redux Toolkit, so it stores its cache in your Redux store. If you already use Redux, RTK Query is the natural pick because it is included. If you are not on Redux, React Query is the more popular standalone option. That, not React Query vs Redux, is the real apples-to-apples comparison.

Is React Query still relevant in 2026?

Very much. React Query, now TanStack Query v5, is the standard way to manage server state in React, and it is actively maintained. It handles caching, background refetching, request deduplication, and loading and error states with a single hook. If anything it is more relevant now, because it replaced a whole category of hand-rolled Redux data-fetching code that teams used to write and maintain themselves.

Can you use React Query and Redux together?

Yes, and it is a common, healthy setup. React Query manages server state; Redux (or Zustand, or Context) manages client state. They are not competitors, so they sit side by side with no conflict. The real mistake is using Redux for server data that React Query should own. Let each tool handle the kind of state it is designed for and they complement each other cleanly.

Share

Liked this? Let's build something.

I take on a small number of front end and AI-engineering projects, and I'm always up for talking shop. Tell me what you're working on.