What is it?
React Server Components (RSC) split the component tree into two: server
components run on the server and stream HTML + a serialized payload;
client components run in the browser and handle interactivity. Next.js
14+ defaults every component to server; you opt into client with
'use client' at the top of the file.
Why it matters
This is the biggest mental-model shift in React since hooks. Get it wrong and you ship state libraries to the server (errors), or hooks to the server (errors), or 800 KB of unnecessary JS to the client (slow). Get it right and your bundles shrink while the data fetching gets simpler.
What to learn
- Why RSC exists: smaller bundles, simpler data fetching, streaming
- The default is server —
'use client'is the opt-in - What server components can do: async, fetch directly, no hooks
- What client components can do: hooks, event handlers, browser APIs
- The boundary: server components can render client components, but not vice versa
- Passing data across the boundary: serializable props only
- Server Actions for mutations from client components
Common pitfall
Adding 'use client' to fix one error and accidentally pulling a huge
subtree to the client. The directive cascades — every imported
component below it becomes client too. Push the boundary as deep as
possible: keep parents server, mark only the leaf that needs hooks.
Resources
Primary (free):
- React docs — Server Components · docs
- Next.js docs — Server and Client Components · docs
- Dan Abramov — RSCs from scratch · article
Practice
Take a Next.js page that uses useState everywhere. Refactor: identify
which subtrees genuinely need interactivity (form, button click,
animation). Push 'use client' down to those leaves only. Compare the
client bundle size before and after. Done when client JS shrinks
visibly and behavior is unchanged.
Outcomes
- Decide whether a component should be server or client by default (server).
- Push
'use client'as deep as possible, not as the page-level default. - Pass server-fetched data to client components via props.
- Use server actions for mutations instead of API routes when it fits.