Server Components vs Client Components in Next.js
React Server Components, Client Components, use client directive, when to use each, serialization, interactivity boundary
Two Types of Components
Every component in the App Router is a Server Component by default. Server Components execute on the server, their output is sent as HTML, and zero JavaScript for that component reaches the browser. This is fundamentally different from anything in the Pages Router or Create React App.
// Server Component (default) โ no directive needed
export default async function ProductList() {
const products = await db.query('SELECT * FROM products')
return <ul>{products.map(p => <li key={p.id}>{p.name}</li>)}</ul>
}When You Need a Client Component
Add 'use client' at the top of the file when the component needs:
'use client'
// Needed for: useState, useEffect, onClick, onChange,
// browser APIs, third-party libraries that use hooks
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(c => c + 1)}>{count}</button>
}The Boundary Rule
Client Components cannot import Server Components. But Server Components can import and render Client Components. This means interactivity lives at the leaves of your component tree, not the root. Keep Client Components small and focused on interaction. Do data fetching in Server Components to reduce client-side JavaScript and improve performance.
If a Server Component needs to pass data to a Client Component, the data must be serializable โ no functions, no class instances, no Promises.
