React continues to evolve, and with React 19, a new hook called use() has been introduced. This has led to confusion: Do we still need libraries like React Query and Redux?
The short answer: Yes — but for different reasons.
In this article, we’ll break down the roles of:
use() (React 19 built-in)So you can understand when to use which — and why.
| Tool | Manages | Best For |
|---|---|---|
use() | Single async reads | Fetching data directly in Suspense-enabled components |
| React Query | Server state | APIs, caching, background updates, syncing UI with remote data |
| Redux (or Zustand) | Client/UI state | Modals, filters, UI selections, app logic, global UI state |
use() in React 19?use() lets React suspend rendering while waiting for a Promise, context, or server function call. It makes fetching in components cleaner, but only handles the initial read of data.
import { use } from "react";function Pokemon() {const pokemon = use(fetch("https://pokeapi.co/api/v2/pokemon/pikachu").then(res => res.json()));return <h1>{pokemon.name}</h1>;}
Wrapped in Suspense:
<Suspense fallback="Loading..."><Pokemon /></Suspense>
use() does not:It simply waits once and renders. Great for Server Components, SSR, and cases where caching doesn’t matter.
React Query is made for server state — data that lives on the backend, changes over time, and needs syncing with UI.
import { useQuery } from "@tanstack/react-query";const { data, isLoading } = useQuery({queryKey: ["pokemon", "pikachu"],queryFn: () => fetch("https://pokeapi.co/api/v2/pokemon/pikachu").then(res => res.json())});
| Feature | Provided? |
|---|---|
| Caching | ✅ |
| Background refetch | ✅ |
| Auto retry | ✅ |
| Sync between tabs | ✅ |
| Works offline | ✅ |
| Optimistic UI updates | ✅ |
| DevTools | ✅ |
React Query is best when:
use() cannot replace that.
Redux (or Zustand / Jotai / Recoil) manages client state, not server state.
| Task | Should You Use Redux? |
|---|---|
| API data caching | ❌ |
| Data that changes on the server | ❌ |
Redux is purely for UI logic.
| Use Case | Best Tool | Why |
|---|---|---|
| Fetch data once in a server component | use() | Simple & clean |
| Fetch data with caching, refetching, stale prevention | React Query | Smart server state management |
| Manage UI-only state (theme, dropdown state, page filters) | Redux / Zustand | App logic stays predictable |
| Infinite scroll / pagination | React Query | Built-in pagination helpers |
| Multi-step form state | Redux / Zustand | State belongs to UI, not API |
| Live dashboard / background refetch | React Query | Sync UI automatically |
use()handles reading async data. React Query handles managing and syncing async server data. Redux handles internal UI and business logic state. They don’t replace each other — they complement each other.
Server Components → Fetch with async/await or use()Client Components → Data syncing with React QueryUI State → Zustand / Redux / useReducer
This gives you: