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
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>
)
}
β 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
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>
)
}
β 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)
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)