Next.js Server Components
React Server Components in Next.js — rendering on the server
What you'll learn
Understand the fundamental difference between Server and Client Components
Know which React features are available in each component type
Co-locate Client Components inside Server Components strategically
Use the 'use client' directive and understand its bundler implications
Pass Server Component results as props to Client Components
Avoid common mistakes: serialization issues, missing directives, context in server
React Server Components (RSC) let you render components on the server, sending only the HTML to the client. This reduces bundle size and improves performance.
Server vs Client Components
| Aspect | Server Component | Client Component |
|---|---|---|
| Rendering | Server only | Browser + server |
| Bundle size | Zero JS | Full JS included |
| State / Effects | Not supported | Full support |
| Database access | Direct | Via API |
| Hooks | No | Yes |
Default: Server Components
In Next.js App Router, all components are Server Components by default:
// app/page.tsx — Server Component (no "use client")
import { getPosts } from "@/lib/db"
export default async function Page() {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
Client Components
Add "use client" to use hooks, event handlers, or browser APIs:
"use client"
import { useState } from "react"
export default function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>
}
Server Component Benefits
- Smaller JS bundles — interactive components only
- Direct data access — no API layer needed
- Automatic code splitting — per-component
- Streaming — send HTML as it renders
Pattern: Server + Client
Wrap interactive client components inside server components:
// Server Component
export default async function Page() {
const data = await fetchData()
return <ClientList items={data} />
}
// Client Component
;("use client")
function ClientList({ items }: { items: Item[] }) {
const [filter, setFilter] = useState("")
// ... interactive filtering
}
Next Steps
- Data Fetching — Fetching data in RSC
- Routing — App Router patterns
Key Takeaways
Server Components run exclusively on the server — they cannot use useState, useEffect, event handlers, or browser APIs
Client Components are bundled and sent to the browser — they can use anything a React component normally can
The 'use client' directive is a bundler instruction that marks the component file's boundary, not a runtime directive
Server Components can import and render Client Components, but not vice versa without composition patterns
Passing Server Component results as props to Client Components enables a 'fetch on server, interact on client' pattern