Why I Stopped Using Global State Libraries
Between React Server Components, URL state, and context, most apps dont need Redux or Zustand anymore.
The Old Default
For years, dropping in Redux (or later Zustand, Jotai, Recoil) was the first step of every React project. The assumption was that components scattered across the tree need a shared bucket of state, and only a global store can provide that.
That assumption is worth questioning.
Three Things That Replace Global State
1. URL as State
Filters, pagination, search queries, selected tabs — all of these belong in the URL. Putting them in a global store means you lose browser history navigation, shareability, and the ability to deep-link.
// Instead of: store.setFilter('status', 'active')
// Do:
const [searchParams, setSearchParams] = useSearchParams();
const status = searchParams.get('status') ?? 'all';
2. Server State
Data from your API is not client state — it’s a cache of server state. Libraries like TanStack Query or the built-in use() hook with React Server Components handle loading, error, and stale-while-revalidate patterns better than any global store ever could.
Since React 19, you can fetch data directly in server components and pass it down:
// Server Component — zero JS sent to client
async function ProjectList() {
const projects = await db.query('SELECT * FROM projects');
return <ul>{projects.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
3. Context for Truly Global Concerns
Themes, auth state, locale — these are legitimately global and affect the entire tree. React Context handles them well, and for most apps, one or two contexts are all you need.
When I Still Use Zustand
There is one case where I still reach for Zustand: complex client-side state that crosses component boundaries and changes frequently. A drag-and-drop board, a real-time collaborative document, or a multi-step form with validation across steps.
But that’s the exception, not the default.
The Balance
My rule of thumb now: start with URL params for UI state, server state libraries for data, and context for auth/theme. Add a global state library only when you can point to a concrete problem that the first three don’t solve.