Client vs. Server State

Why putting your API data into your global UI store is an anti-pattern, and how modern React separates the two.

React4 min readConcept 26 of 46

The Two Types of State

**Client State (UI State):** Data that your React app completely owns. It is synchronous, temporary, and lost when you refresh the page. Examples: Is this dropdown open? Is dark mode on? What did the user type into this uncontrolled input?

**Server State (Remote Data):** Data that fundamentally belongs to a database on a server. It is asynchronous, persistent, and shared among many users. Examples: A list of products, a user's profile details.

The Redux Mistake

For years, React developers put *everything* into global state managers like Redux.

But putting Server State into Client State is a nightmare. Because it's asynchronous, you suddenly have to manage isLoading, isError, and data manually for every single API call. Worse, the moment you put the data in Redux, it is 'stale' (out of date), because someone else might have updated the database.

You end up writing hundreds of lines of code just to handle caching and background updates.

The Modern Split

Modern React architecture draws a hard line between these two:

1. **Use a UI Store (Zustand, Context) ONLY for Client State.** (e.g., setDarkMode(true))

2. **Use a Server Cache (React Query, SWR, Apollo) for Server State.** These tools aren't 'state managers'—they are caching layers that automatically handle loading states, error retries, background fetching, and cache invalidation.

The Great Divide

Compare the characteristics of Client State vs Server State. Notice how different the problems are that they need to solve.

Client State (UI)

Owned by the browser. Synchronous.
Lost on refresh.

User ActionToggle Theme
Local Store (Zustand){ theme: 'dark' }
FastSynchronousNo Loading States

Server State

Owned by the DB. Asynchronous.
Needs caching layer.

UI Component
Async Cache (React Query)
isLoadingisStaledata
Remote Database[Users List]
Slow / AsyncRequires Error HandlingCan be stale

Client state (left) is fast, synchronous, and lives in memory. Server state (right) requires crossing a network boundary, handling loading states, and maintaining a local cache to stay perfectly synced.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1Which of the following is the best example of Client State?
  2. 2Why is it an anti-pattern to store API data in a standard state manager like `useState` or Redux?
  3. 3What is the modern tool of choice for managing Server State in React?

Remember this

  • Client State is synchronous UI data (owned by the browser).
  • Server State is asynchronous remote data (owned by the database).
  • Never put Server State into a standard Client State manager (like Redux or useState).
  • Use a dedicated caching tool like React Query to handle Server State.
  • Once you separate them, your global UI state becomes drastically simpler.

Done with this concept?

Mark it complete to track your progress. No login needed.