# React Server Components
> Server-rendered components that ship zero JS to the browser.
Frontend architecture guidance from fearchitect, written by Abas Turabli and last reviewed 2026-06-21. Source: https://fearchitect.com/topics/react-server-components
Use it as reference for the task at hand. Before changing code, check this guidance against the codebase: where the code already makes a different, deliberate choice, flag the conflict instead of rewriting it. Library APIs move faster than this guide, so confirm exact signatures in the official docs linked at the end.
## Summary
React Server Components (RSC) run only on the server — they fetch data, render to a wire format, and send the result to the client without bundling their code into the JS payload. Static subtrees add no client JS; interactive parts opt in with `"use client"`. Default in the Next.js App Router.
## Definition
RSC splits the component tree into two worlds: server components run on the server (or at build time), have direct access to databases and secrets, and emit React's wire format — not HTML. Client components, marked `"use client"`, are the interactive islands that hydrate in the browser.
The boundary is explicit: any component that touches `useState`, `useEffect`, or browser APIs must be a client component. Props crossing the boundary must be serializable — strings, numbers, plain objects, arrays — not functions or class instances.
Large, data-heavy subtrees stay server-side, shrinking the JS bundle the browser must parse and execute.
## Diagram
```mermaid
sequenceDiagram
participant Browser
participant Server
Browser->>Server: GET /products/42
Server->>Server: Render server component tree (async, DB access)
Server-->>Browser: HTML shell + RSC payload (streamed)
Browser->>Browser: Hydrate client islands only ("use client" subtrees)
```
Server renders the full tree and streams the RSC payload; only client-component islands hydrate in the browser.
## Request lifecycle
### 1. Server render
Next.js renders the server component tree on the server. Each `async` component `await`s its own data — DB queries, ORM calls, or internal fetches — directly, with no API route needed.
### 2. RSC payload
React produces an RSC payload — a compact wire format encoding the component tree and streamed data — not HTML. This is sent to the client alongside the HTML shell.
### 3. Client reconcile
React's runtime on the client reconciles the payload into the existing DOM. Server components never re-render in the browser; only `"use client"` subtrees hydrate.
### 4. Props serialization
Props flow one-way: server to client, serialized in the payload. Client components can import server components only as props (children or slots), not as direct imports — the bundler enforces this.
## Server component with a client island
The server component fetches data directly; `AddToCartButton` is the only code shipped to the browser. Props passed across the boundary are plain serializable values.
**ProductPage (server) + AddToCartButton (client)**
```tsx
// app/products/[id]/page.tsx — server component (no "use client")
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
// Runs on the server — never exposed to the browser.
const product = await db.product.findUnique({ where: { id } });
return (
{product.name}
{product.description}
{/* Client island — only this subtree ships JS */}
);
}
// components/AddToCartButton.tsx
"use client"; // marks the server/client boundary
import { useState } from "react";
export function AddToCartButton({
productId,
price,
}: {
productId: string;
price: number;
}) {
const [added, setAdded] = useState(false);
return (
);
}
```
`db` never reaches the browser. `"use client"` is the boundary directive — everything above it stays server-only. Props are serializable strings and numbers.
## Tradeoffs
**Pros**
- Zero JS shipped for server-only components — smaller bundles, faster parse.
- Data fetching co-located with the component; no API route required.
- DB credentials and secrets stay on the server by default.
- Async server components eliminate client-side data-fetching waterfalls.
**Cons**
- Props crossing the boundary must be serializable — no functions.
- No `useState`, `useEffect`, or browser APIs inside server components.
- Two component types add mental overhead for teams new to RSC.
- Server render and client hydration are separate phases — harder to debug.
## Watch out: Common pitfalls
Passing non-serializable props (functions, class instances) across the boundary crashes at runtime. Marking too many components `"use client"` negates bundle savings — keep islands small and at the leaves. Context providers must be client components, so server components cannot consume React context. In Next.js 15+, `params` and `searchParams` are async Promises and must be awaited.
## Key terms
- **RSC payload**: React's compact wire format encoding the server-rendered component tree, streamed to the client.
- **"use client"**: Directive marking the file as a client component boundary; bundler includes it in the JS bundle.
- **Serializable props**: Props that survive JSON serialization: strings, numbers, plain objects, arrays — not functions.
- **Client island**: A `"use client"` subtree embedded inside a server-rendered tree that hydrates independently.
## Related topics
- [Streaming SSR](https://fearchitect.com/topics/streaming-ssr.md): Flush the HTML shell immediately, then stream the rest as Suspense resolves.
- [Partial Prerendering (PPR)](https://fearchitect.com/topics/partial-prerendering.md): Static CDN shell plus dynamic Suspense holes in one response.
- [Hydration Strategies & Islands](https://fearchitect.com/topics/hydration-and-islands.md): Pay JS cost only for interactive regions, not the whole page.
- [Rendering Strategies: CSR / SSR / SSG / ISR](https://fearchitect.com/topics/rendering-strategies.md): Where and when HTML is generated: build, request, browser, or revalidated.
- [Resumability (Qwik)](https://fearchitect.com/topics/resumability-qwik.md): Skip hydration by serializing state and listeners directly into HTML.
- [Component Architecture & Project Structure](https://fearchitect.com/topics/component-architecture.md): Structuring components so composition beats configuration.
## Further reading
- [React — Server Components](https://react.dev/reference/rsc/server-components)
- [Next.js — Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components)
- [React — "use client"](https://react.dev/reference/rsc/use-client)