Script Valley
Next.js: Full-Stack React Applications
Next.js Foundations and Project SetupLesson 1.4

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.

Up next

How to fetch data in Next.js Server Components

Sign in to track progress