Server Components Overview
React Server Components run on the server: zero client JS for their logic, async data, and composition with client leaves.
- react
- server-components
Server Components (RSC) render on the server into a special payload the client hydrates selectively. They can be async, read databases and secrets (with care), and do not ship their own component logic as client JS. Interactive islands opt into Client Components.
Docs: Server Components, Next.js.
What you gain
| Benefit | Why |
|---|---|
| Smaller bundles | Server-only code never goes to the client |
| Direct data access | await db.query in the component |
| Secure by default | Secrets stay server-side |
| Streaming | Frameworks can stream UI as data resolves |
What you cannot do on the server
useState,useEffect, browser DOM APIs- Event handlers like
onClickon the server component itself - Importing client-only libraries without a client boundary
Composition
// Server
async function Notes() {
const notes = await getNotes();
return (
<ul>
{notes.map((n) => (
<li key={n.id}>
{n.title}
<EditButton noteId={n.id} /> {/* client */}
</li>
))}
</ul>
);
}
Keep client boundaries at interactive leaves.
Mental model versus classic SSR
Classic SSR still sent a full client React tree to hydrate. RSC can keep large pure UI server-only. Hydration applies mainly to client islands. Mismatches still matter for those islands (hydration).
Interview out-loud
“Server Components render on the server, can be async, and avoid shipping their logic to the client. I fetch data on the server, pass serializable props to client children, and use composition so client shells wrap server content via children. Hooks and browser APIs require Client Components.”
Related on this site
Further reading
Edge cases worth rehearsing
Interviewers and production incidents cluster around the same edges: first render versus update, empty and loading states, Strict Mode double setup, concurrent interruptions, and what happens when identity (key, route params, user id) changes mid-edit. Walk one concrete user journey end-to-end — open, edit, navigate away, come back — and say which state survives.
Prefer fixing data flow and ownership before reaching for memoization or micro-optimizations. Prefer event handlers over effects when a user action is the trigger. Prefer deriving values during render over mirroring props into state. Prefer stable list keys from business ids. Measure with the profiler when performance is the claim.
When you cite an API, mention one failure mode: abort on unmount, serializable props across server/client boundaries, focus restoration for dialogs, or cache invalidation after a mutation. Specific beats generic every time.
Edge cases worth rehearsing
Interviewers and production incidents cluster around the same edges: first render versus update, empty and loading states, Strict Mode double setup, concurrent interruptions, and what happens when identity (key, route params, user id) changes mid-edit. Walk one concrete user journey end-to-end — open, edit, navigate away, come back — and say which state survives.
Prefer fixing data flow and ownership before reaching for memoization or micro-optimizations. Prefer event handlers over effects when a user action is the trigger. Prefer deriving values during render over mirroring props into state. Prefer stable list keys from business ids. Measure with the profiler when performance is the claim.
When you cite an API, mention one failure mode: abort on unmount, serializable props across server/client boundaries, focus restoration for dialogs, or cache invalidation after a mutation. Specific beats generic every time.
Related guides
- Accessibility Patterns in ReactPractical React a11y: labels, focus management, keyboard, live regions, and composition patterns that stay accessible.
- Avoid Prop Drilling with CompositionStop threading props through intermediates: children slots, inversion of control, and when context is the right escape hatch.
- Batching State UpdatesHow React 18+ batches setState in events, timeouts, and promises: when updates flush and why double setState still works.
- Children Prop PatternsUsing children and slot props for flexible APIs: wrappers, compound components, and when to prefer explicit props.
- Client Component BoundariesWhere to put use client: push interactivity to leaves, serializable props, and children as server slots.