DEV Community

Cover image for Redux Toolkit vs React Query: Do You Really Need Both? πŸ€”
Taron Vardanyan
Taron Vardanyan

Posted on

Redux Toolkit vs React Query: Do You Really Need Both? πŸ€”

For years, Redux was the go-to for state management in React apps.

Then came React Query (now TanStack Query) β€” and it changed how we handle server state forever.

But here's the confusion many developers face:

β€œIf I’m using React Query, do I still need Redux?”

β€œCan Redux Toolkit replace React Query?”

Let’s clear the fog. 🌫️


🧠 First β€” Two Different Problems

Before comparing them, it’s crucial to understand what each tool actually manages.

Type of State Description Example
Client State Data that exists only in the UI or app memory. Modal open/close, filters, active tab
Server State Data fetched from APIs or databases, often cached. Users list, product data, comments
  • 🧩 Redux Toolkit (RTK) β†’ best for client state
  • 🌐 React Query β†’ best for server state

🧩 Redux Toolkit Overview

Redux Toolkit (RTK) is the official, modern way to write Redux β€” without the boilerplate.

It’s great for:

  • Local or global UI state
  • Caching small API responses
  • Complex app logic
  • Predictable, centralized state updates

Installation

npm install @reduxjs/toolkit react-redux
Enter fullscreen mode Exit fullscreen mode

Example

import { createSlice, configureStore } from '@reduxjs/toolkit'
import { Provider, useSelector, useDispatch } from 'react-redux'

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value++ },
  },
})

const store = configureStore({
  reducer: { counter: counterSlice.reducer },
})

function Counter() {
  const count = useSelector((state) => state.counter.value)
  const dispatch = useDispatch()
  return (
    <button onClick={() => dispatch(counterSlice.actions.increment())}>
      Count: {count}
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Predictable, centralized store
  • Time-travel debugging and middleware
  • Immutable updates via Immer
  • Integration with async logic via createAsyncThunk
  • Scales beautifully for enterprise apps

⚠️ Cons

  • Boilerplate compared to local hooks
  • Manual caching and invalidation for API data
  • More setup for smaller apps

🌐 React Query (TanStack Query) Overview

React Query manages remote data fetching, caching, and syncing β€” not app logic.

It automates the painful parts of server-state management:

  • Fetching
  • Caching
  • Stale data invalidation
  • Background updates
  • Pagination & optimistic updates

Installation

npm install @tanstack/react-query
Enter fullscreen mode Exit fullscreen mode

Example

import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

function Todos() {
  const { data, error, isLoading } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/api/todos').then(res => res.json())
  })

  if (isLoading) return <p>Loading...</p>
  if (error) return <p>Error: {error.message}</p>

  return (
    <ul>
      {data.map(todo => <li key={todo.id}>{todo.title}</li>)}
    </ul>
  )
}
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Automatic caching and refetching
  • Handles background sync and retry logic
  • No reducers or actions β€” pure hooks
  • Amazing devtools for debugging
  • Ideal for data-heavy apps (dashboards, SaaS)

⚠️ Cons

  • Not designed for client UI state
  • No central store or global reducer logic
  • Limited control over global mutation side-effects

βš”οΈ Head-to-Head Comparison

Feature Redux Toolkit React Query
Primary Focus Client/Global State Server/Remote State
Data Source Local or manual API calls Fetched via queries
Caching Manual Automatic
Invalidation Manual Automatic
Setup Complexity Moderate Simple
Global Store Yes No
DevTools Redux DevTools React Query Devtools
Best For State logic, app-wide control Fetching & syncing backend data

πŸ”€ Can You Use Both Together?

Absolutely β€” and many real-world apps do. πŸ’ͺ

They solve different concerns, and together they shine:

  • Use React Query for all server communication
  • Use Redux Toolkit for UI and app logic

Example integration:

// react-query handles data
const { data: todos } = useQuery(['todos'], fetchTodos)

// redux handles UI
const filter = useSelector(state => state.filter.value)
const filteredTodos = todos?.filter(todo => todo.status === filter)
Enter fullscreen mode Exit fullscreen mode

This approach keeps your data layer and UI layer cleanly separated.


🧩 TL;DR

You Need... Use
To manage app-wide UI state Redux Toolkit
To handle API fetching and caching React Query
To replace Redux entirely React Query + local state
To handle everything with structure Combine both

πŸ’¬ Final Thoughts

Redux Toolkit and React Query aren’t competitors β€” they’re complements.

Think of them like this:

🧠 Redux: Your app’s brain (logic, actions, state)

🌍 React Query: Your app’s bloodstream (data flow and sync)

Use the right tool for the right job β€” and your React app will stay clean, fast, and predictable.


If you liked this post, follow me for more deep dives on React architecture and state management!

πŸ‘‰ @taronvardanyan

Top comments (0)