Client state vs server state: understanding the difference
client state definition, server state definition, why they need different tools, synchronization problem, stale data, local vs remote ownership, state categories
Two Types of State in React Apps
One of the biggest architecture mistakes in React is treating all state the same. There are two fundamentally different categories, and conflating them leads to bugs.
Client State
Data your app owns and controls: UI toggles, form inputs, modal open/closed, selected tab, theme. Lives entirely on the client. Changes synchronously. Never goes out of sync because nothing external can change it.
Server State
Data that lives on a server: users, products, orders, posts. Your app doesn't own it โ the server does. It changes asynchronously. Goes stale. Multiple browser tabs can show different versions. Needs loading and error handling.
// Client state โ local, synchronous
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [selectedTab, setSelectedTab] = useState('overview');
// Server state โ remote, async, can go stale
const { data: users, isLoading } = useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then(r => r.json())
});Use Context or Zustand for client state. Use React Query, SWR, or RTK Query for server state. Putting server data into Context or Redux requires manually handling loading, error, caching, and revalidation โ React Query handles all of this by default.
