React Server Components represent a fundamental shift in how we think about state in React applications. The traditional client-side state management patterns — Redux, Zustand, Context — assume that the component tree lives entirely in the browser. RSCs shatter that assumption.
Server Components cannot use useState, useEffect, or any React hooks. They run exclusively on the server and stream HTML to the client. This means global client state must be explicitly separated from server-fetched data. The boundary between server and client becomes a first-class architectural concern.
In the App Router, data fetching happens directly in Server Components via async/await. This eliminates the need for client-side data fetching libraries like React Query for server-rendered data. The cache is managed by Next.js's built-in fetch cache and tag-based revalidation system.
Client state is still necessary for truly interactive UI — form state, UI toggles, optimistic updates, and real-time subscriptions. The key insight is: server state belongs in the URL or server cache, client state belongs in lightweight stores (Zustand, jotai) scoped to the client boundary.
We've settled on a pattern where Server Components own all data fetching and initial render, Client Components own interactivity, and Server Actions handle mutations with immediate cache invalidation via revalidateTag. This keeps bundles lean, TTFB fast, and the mental model clean.
Frontend engineer at XDigital. Passionate about React Server Components and modern data fetching patterns.
View all postsWe bring the same precision to every build. Tell us what you are working on.