Lesson 1 / 25
Local, Server and Global Client State
Three kinds of state, three homes.
Classify before you choose
Local UI state belongs to one component or a small subtree: whether a dropdown is open, the text in an input, the current tab. useState or useReducer is the right home. Server state is a cached copy of data owned by a backend: it can go stale, needs loading and error flags, refetching and deduplication. Global client state is data the client owns that many distant components read or change: the signed-in user's preferences, a shopping cart before checkout, a multi-step wizard, an editor document. Only the last kind is the classic job of a global store such as Redux or Zustand.
Not all state belongs in a store
Before reaching for a library, classify your state and keep data flowing in one direction.
Three kinds of state in one screen
A product page, annotated.
function ProductPage({ id }: { id: string }) {
// local UI state: only this component cares
const [qty, setQty] = useState(1);
// server state: a cached copy of backend data (RTK Query, TanStack Query, ...)
const { data: product, isLoading } = useGetProductQuery(id);
// global client state: the cart is read by the header, drawer and checkout
const dispatch = useAppDispatch();
const addToCart = () => dispatch(cartAdded({ id, qty }));
if (isLoading || !product) return <Spinner />;
return <ProductView product={product} qty={qty} onQty={setQty} onAdd={addToCart} />;
}Keep state as local as possible
Lift state up only when a second component genuinely needs it. Putting every input value in a global store makes code harder to follow and can cause unnecessary re-renders.
Quick check: Which is best described as server state?
- The text typed in a search box
- Whether a modal is open
- A list of orders fetched from an API that may become stale
- A theme preference that never leaves the browser
Answer
A list of orders fetched from an API that may become stale — Server state is a cache of data owned elsewhere, so it needs fetching, invalidation and refetching.