Comparing URL state, React Context, Zustand, and Server Actions—choosing the right state boundary for your app.

The Article
The full story, in the order it happened.
In the early days of React, Redux was boilerplate gospel. Today, modern state architecture focuses on placing state as close to where it is needed as possible and recognizing that server state and client state are distinct problems.
1. URL State for Shareable UI
Search filters, pagination indices, selected tabs, and active modal IDs belong in the URL query string (useSearchParams or nuqs). Storing this in URL params makes states shareable, bookmarkable, and history-friendly.
2. Server State vs Client State
With React Server Components and Server Actions, most data fetching and mutation handling bypasses client state entirely. Data is fetched on the server and cached automatically.
3. Lightweight Client Stores: Zustand
For truly global client-side state (such as audio player queues, user theme toggles, or shopping cart drawers), small atomic stores like Zustand provide zero-boilerplate state access without provider wrapping:
import { create } from 'zustand';
interface Store {
count: number;
increment: () => void;
}
export const useStore = create<Store>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));

Tahmid Hasan
Web developer and UI designer building fast, accessible interfaces — and writing down what he learns along the way.
ABOUT ME