Here is a 5-minute read article to remind you about Server and Client components—perfect for quick review before interviews or when writing modern React apps.
React and Next.js 14+ introduced Server Components (RSC) and Client Components to optimize rendering and performance. This architecture allows developers to choose where components execute—on the server or in the browser—resulting in smaller bundles, faster loads, and cleaner architecture.
Rendering Environments
React separates logic into two environments:
- Client (Browser) — For interactivity, state, and DOM effects
- Server (Node.js) — For data fetching, caching, and secure logic
Use "use client"
and "use server"
directives to explicitly control this boundary.
Server Components
Benefits
- Data Fetching on the server
- Security by hiding sensitive logic
- Caching and performance optimization
- SEO & Shareability
- Streaming: progressive loading via chunks
- Smaller JS bundle
Default in Next.js
Next.js uses Server Components by default. Rendering flow:
New Request
↓
Server renders Server Components → RSC Payload → Sent to client
↓
Client renders UI & hydrates Client Components
Client Components
Use when you need:
- Interactivity (
useState
,useEffect
, DOM events) - Access to Browser APIs (e.g.,
localStorage
,geolocation
)
Place "use client"
at the top of the component.
Composition Patterns
Sharing Data
Use fetch
or React.cache()
in Server Components to fetch and reuse data.
Client Components Down the Tree
Move Client Components as deep as possible to minimize bundle size.
Props Serialization
Pass props from Server → Client via serialization (only serializable values!).
Rendering Strategies
1. Static Rendering (default)
- Cached at build or revalidated in background
- Great for non-personalized pages (e.g., blog posts, product listings)
2. Dynamic Rendering
- Used when data is personalized (cookies, headers, searchParams)
- Rendered per-request
Switching to Dynamic Rendering
Uses Dynamic API | Data Cached | Resulting Strategy |
---|---|---|
No | Yes | Static Rendering |
Yes | Yes | Dynamic Rendering (cached) |
No | No | Dynamic Rendering |
Yes | No | Dynamic Rendering |
Streaming
- Streams UI from server as chunks become ready
- Built into Next.js App Router using Server Actions + React Suspense
Example
Server Component
// app/page.tsx
import { fetchProducts } from "@/lib/data";
export default async function Page() {
const products = await fetchProducts(); // Server-side
return (
<div>
<h1>Our Products</h1>
<ProductList products={products} />
</div>
);
}
Client Component
// components/ProductList.tsx
"use client";
import { useState } from "react";
export default function ProductList({ products }) {
const [highlight, setHighlight] = useState(false);
return (
<ul onMouseEnter={() => setHighlight(true)}>
{products.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
);
}
Diagram – RSC Payload Rendering
New Request
↓
[ Server ]
Render Server Components
↓
RSC Payload (binary format)
↓
[ Client ]
1. Hydrate HTML
2. Reconcile Server and Client Components
3. Activate JS for interactive Client Components
RSC Payload
is a compact binary format sent from server → client with the rendered component tree.
Summary
- Use Server Components for logic, data, and performance
- Use Client Components only for interactivity
- Pass only serializable props across boundaries
- Stream content progressively when possible
Top comments (0)