React Server Components — What Actually Changes
The mental model shift from client-first to server-first React: when to reach for "use client", what stays on the server, and why the boundary matters.
Server Components are the biggest shift in React's component model since hooks. After shipping several App Router projects, here is how I actually think about them day-to-day.
The Default Is Now Server
In the App Router, every component is a Server Component unless you opt out with "use client". This is the opposite of the old mental model. The question changes from "should I fetch this on the server?" to "does this component need the browser at all?"
The Client Boundary
"use client" marks a boundary — not a single component. Every component imported below a "use client" file becomes part of the client bundle automatically, even if it doesn't use any browser APIs. Keep client components as leaves: small, focused on interactivity.
What Stays on the Server
- Database and filesystem reads
- Auth token verification
- API calls to services that need secrets
- Large dependencies (parsing libraries, SDKs) that only need to run once
What Requires the Client
useState,useEffect, and all other hooks- Browser APIs (
window,document,navigator) - Event handlers (
onClick,onChange) - Third-party libraries that depend on any of the above
Server Components Are Not API Routes
A common confusion: you cannot call a Server Component from a client-side event handler. They render once on the server as part of the React tree. For mutations and on-demand server logic, use Server Actions ("use server") or a regular API route.