
Every new React project seems to start the same way: install a state management library, create a store, and start pumping data into it. Redux, Zustand, Jotai: the options have multiplied, but the underlying assumption hasn't changed. We treat global state as the default rather than the last resort.
In practice, the vast majority of state in a typical web app is either server-derived data that belongs in a cache, or local UI state that lives naturally in a single component. Once you separate those two categories, the amount of truly global, client-only state shrinks dramatically.
Libraries like React Query and SWR made this distinction mainstream. When you fetch a list of users, that data doesn't belong in a Redux store. It belongs in a cache with its own invalidation, deduplication, and background refresh logic. Treating server data as a cache rather than state eliminates an entire class of synchronization bugs.
// Instead of dispatching to a global store:
dispatch(fetchUsers());
// Treat it as a cache entry:
const { data: users } = useQuery({
queryKey: ['users'],
queryFn: () => api.getUsers(),
});The best state architecture is the one with the least surface area. Every piece of state you add to a global store is a piece you have to synchronize, debug, and maintain. Start local, stay local as long as you can, and only reach for a shared store when the alternative is genuinely worse.