It’s 2026.
And please… don’t be a stupid developer like me.
Yes, I said it 😄
For a long time, I used Redux (and sometimes Context) for everything.
University projects? Redux.
Side projects? Redux.
Fetching data from APIs? Yup… Redux again.
Then one day, a senior dev casually asked me:
“Bro… are you still using Redux to manage server state?”
I was like:
“Server… state? Isn’t state just… state?” 🤯
Turns out — nope.
And that question sent me down a rabbit hole that introduced me to React Query (now TanStack Query).
At that time, I was proudly pouring API responses into Redux like Dumbledore saying
“Of course I know what I’m doing.”
(First-year engineer confidence is undefeated.)
This article is my attempt to end the confusion between client state and server state, without turning this into a boring 40-minute read.
🧠 What the heck is Server State?
Server state is data that comes from somewhere outside your app — usually an API.
It’s data that:
- Comes from an API
- Can be cached
- Can become stale
- Can be refetched
- Can change without you doing anything (thanks other users 👋)
Examples:
- Product list
- User profile from backend
- Orders
- Search results
- Paginated data
👉 React Query is built specifically to manage this kind of state
🎨 What is Client State then?
Client state lives purely inside your UI.
It’s data that:
- Exists only in the browser
- Is usually synchronous
- Is not shared with other users
Examples:
- Dark / light theme
- Modal open / close
- Selected filters (before calling an API)
- UI auth state (not the API call itself)
👉 Redux still shines here
⚔️ Why this matters (and why Redux alone struggles)
Most web frameworks don’t tell you how to fetch and manage async data properly.
So we end up:
- Writing
useEffect+useStateeverywhere - Storing API responses in Redux
- Manually handling loading, error, caching, refetching… again and again
Traditional state libraries are great for client state,
but server state is a different beast:
- It lives remotely
- It’s async
- It can change without you knowing
- It gets stale
- It needs caching
- It needs background updates
- It needs pagination, deduping, memory management…
If you’re not overwhelmed by that list, congrats — you deserve an award 🏆
For the rest of us… this is where TanStack Query comes in.
🚀 Why React Query?
TanStack Query is hands-down one of the best tools for managing server state.
- Works out of the box
- Almost zero config
- Handles the hard stuff for you
- Scales as your app grows
Alright, enough theory.
Let’s see why React Query is actually better than the “classic React way”.
✅ Example 1: Fetching Data (useEffect vs useQuery)
❌ Classic React Way
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetchProducts()
.then(res => setData(res))
.catch(err => setError(err))
.finally(() => setLoading(false));
}, []);
Problems:
- Boilerplate everywhere
- Manual loading & error handling
- No caching
- No refetching
✅ React Query Way
const { data, isLoading, isError } = useQuery({
queryKey: ['products'],
queryFn: fetchProducts,
});
🎉 Done.
- Loading handled
- Error handled
- Cached
- Refetched automatically
✅ Example 2: Caching (the silent killer)
❌ Classic Way
- Navigate away → fetch again
- Come back → fetch again
- Same API call 10 times 🤦♂️
You either:
- Accept it
- Or write your own cache logic (good luck)
✅ React Query Way
useQuery({
queryKey: ['products'],
queryFn: fetchProducts,
staleTime: 5 * 60 * 1000,
});
React Query:
- Caches data
- Knows when data is stale
- Refetches only when needed
You didn’t write any caching code.
✅ Example 3: Mutations & Refetching
❌ Classic Way (Redux / manual)
- Call API
- Update Redux
- Refetch list
- Sync UI manually
Lots of moving parts.
✅ React Query Way
const mutation = useMutation(addProduct, {
onSuccess: () => {
queryClient.invalidateQueries(['products']);
},
});
What happens:
- API call succeeds
- Cached data invalidated
- List refetches automatically
- UI updates itself
✨ Less code. Fewer bugs. Less stress.
🧩 Final Takeaway
If there’s one thing I wish someone had told me earlier, it’s this:
Not all state is the same.
Server state is messy, asynchronous, shared, and constantly changing.
Client state is local, predictable, and UI-focused.
Trying to manage both with the same tool (hello Redux-for-everything 👋) works…
but it also means writing a lot of code that React Query already solved.
So no, React Query doesn’t replace Redux.
It replaces painful server-state logic you shouldn’t be writing in 2026.
If this article made you question where your API data lives —
good. That’s exactly the point.
Now go try React Query.
Your future self (and your codebase) will thank you.
Top comments (0)