DevAcademy
LearnReactServer vs Client Components
AdvancedReact

Server vs Client Components

Understand the React Server Component model — what runs on the server, what runs in the browser, and how the two work together.

Reading Time

16 min

Lesson

Lesson 37 of 42

Two Kinds of Components Now Exist

Modern React (used through frameworks like Next.js) distinguishes between Server Components, which render on the server and send only the resulting HTML/data to the browser, and Client Components, which render in the browser and can use state, effects, and browser APIs.

Server vs Client Components

Server ComponentClient Component
Runs whereOn the server onlyIn the browser (and initially on the server for SSR)
Can use useState/useEffectNoYes
Can access the filesystem/database directlyYesNo
Ships JavaScript to the browserNo (zero JS for this component)Yes
Declared withThe default — no directive needed"use client" at the top of the file

A Server Component (Default)

// This runs only on the server — its code never ships to the browser.
async function ProductList() {
  const products = await db.query("SELECT * FROM products");

  return (
    <ul>
      {products.map((p) => <li key={p.id}>{p.name}</li>)}
    </ul>
  );
}

A Client Component

"use client";

import { useState } from "react";

function LikeButton() {
  const [liked, setLiked] = useState(false);

  return (
    <button onClick={() => setLiked(!liked)}>
      {liked ? "❤️ Liked" : "🤍 Like"}
    </button>
  );
}

Why This Split Exists

Server Components can fetch data directly (no client-side API round trip needed) and never add to the JavaScript bundle sent to the browser. Client Components are still necessary for anything interactive — state, event handlers, effects, browser-only APIs.

Composing Server and Client Components

A Server Component can render a Client Component as a child, passing serializable data as props. A Client Component, however, cannot import and directly render a Server Component — data flows from server to client, not the other way around.

A Server Component Rendering a Client Component

// page.jsx — Server Component (no "use client")
import LikeButton from "./LikeButton"; // Client Component

async function ProductPage({ params }) {
  const product = await getProduct(params.id);

  return (
    <div>
      <h1>{product.name}</h1>
      <LikeButton /> {/* interactive island inside a server-rendered page */}
    </div>
  );
}

Props Must Be Serializable

Since Server Components pass data to Client Components across the server/client boundary, props must be serializable (plain objects, strings, numbers, arrays) — you can’t pass a function or a class instance from a Server Component down to a Client Component.

This is a Framework Feature

Server Components require a framework with the right build/runtime support — Next.js’s App Router is the most common way to use them today. Plain React (via Vite, for example) doesn’t have Server Components without such a framework.

Best Practice

Default to Server Components, and mark a component "use client" only when it actually needs interactivity (state, effects, event handlers) or browser-only APIs — pushing "use client" as far down the tree as possible keeps the client JavaScript bundle smaller.

Interview Questions

Quick Quiz

1. Where does a Server Component run?

2. What directive marks a component as a Client Component?

3. Can a Client Component directly import and render a Server Component?