0Pricing
React Academy · Lesson

Server vs Client Components in Next.js

Decide when to add 'use client' and how to compose server and client trees.

Server vs Client Components in Next.js is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Default: Server Components

In the App Router, all components are Server Components by default. They render on the server, have zero client-side JavaScript, and can directly access databases, env variables, and the filesystem.

Opting In to Client Components

Add 'use client' at the top of a file to make it a Client Component. All its imports become client-side too — it creates a client boundary.

'use client';

import { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

What Server Components Can Do

Server Components can await data fetches inline, read environment variables, access the filesystem, and import large server-only packages without increasing the client bundle.

// app/products/page.tsx — Server Component
export default async function ProductsPage() {
  const products = await db.query('SELECT * FROM products');
  return (
    <ul>
      {products.map(p => <li key={p.id}>{p.name}</li>)}
    </ul>
  );
}

What Server Components Cannot Do

Server Components cannot use hooks (useState, useEffect), browser APIs, or event handlers. These require 'use client'.

Composing Server and Client

Pass Server Component output as props/children to Client Components. The golden pattern: keep data fetching in Server Components, interactivity in Client Components.

// Server Component (no 'use client')
async function ProductPage({ id }) {
  const product = await getProduct(id); // direct DB call
  return <AddToCartButton product={product} />; // client component
}

// Client Component
'use client';
function AddToCartButton({ product }) {
  const [added, setAdded] = useState(false);
  return <button onClick={() => { addToCart(product); setAdded(true); }}>{added ? 'Added!' : 'Add to cart'}</button>;
}

Passing Children from Server to Client

A Server Component can pass JSX as children to a Client Component. The children remain server-rendered; the client wrapper adds interactivity.

// Client wrapper — Modal with open/close state
'use client';
function Modal({ children }) {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button onClick={() => setOpen(true)}>Open</button>
      {open && <dialog>{children}</dialog>}
    </>
  );
}

// Server Component — passes server-fetched content into client modal
async function Page() {
  const content = await fetchContent();
  return <Modal><ServerRenderedContent data={content} /></Modal>;
}

The Client Boundary

Adding 'use client' makes the file and all its child imports client-side. To keep a child as a Server Component, pass it as a prop or slot instead of importing directly.

Data Fetching Patterns

Fetch data in Server Components and pass it down. Avoid fetching in Client Components when possible — it adds client bundle weight and duplicates server logic.

// Good: fetch in server, pass to client
async function Page() {
  const user = await getUser();
  return <UserProfile user={user} />; // client component
}

// Avoid: fetch in client
'use client';
function UserProfile() {
  const { data } = useSWR('/api/user', fetcher); // network request from browser
}

Server-Only Utilities

The server-only package throws a build error if a server-only module is accidentally imported into a Client Component.

// lib/db.ts
import 'server-only'; // throws at build time if imported in 'use client' file

export const db = createDbClient(process.env.DB_URL);

Sharing State Between Server and Client

Server Components can't hold state. To share state from a server fetch with interactive client components, pass it as props on initial render, then manage updates in the client.

When to Add use client

Add 'use client' when you need: hooks (useState, useEffect), browser events (onClick), browser APIs (localStorage, window), or third-party client-side libraries.

Quick Check

What must you add to the top of a file to use useState or onClick in Next.js App Router?

Recap

All App Router components are Server Components by default — zero JS bundle, direct data access. Add 'use client' only where you need interactivity. Compose by passing server-fetched data as props or children to client wrappers, keeping the client boundary as leaf-level as possible.

Frequently asked questions

Is the “Server vs Client Components in Next.js” lesson free?

Yes — the full text of “Server vs Client Components in Next.js” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “Server vs Client Components in Next.js”?

Decide when to add 'use client' and how to compose server and client trees. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Server vs Client Components in Next.js” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. App Router File Conventions
  2. Server vs Client Components in Next.js
  3. Dynamic Routes & Route Groups
  4. Metadata API & SEO in App Router
← Back to React Academy