Skip to the solution
MediumFrontend5 min read

What is the difference between Server Components and Client Components in Next.js?

1.2k views

The problem

Question presented to candidate: "In the App Router, what is the difference between a Server Component and a Client Component, how do you decide which to use, and how do they work together?"

What a strong answer should cover:

  • Server Components are the default in app/: they run only on the server, can be async, can read databases and secrets, and send no JavaScript to the browser.
  • Client Components start at a 'use client' file: they are server-rendered to HTML and then hydrated, so they can use state, effects, event handlers and browser APIs.
  • A Client Component cannot import a Server Component, but can receive one as children or props.
  • Props from server to client must be serializable (functions and class instances are rejected).
  • Guideline: keep data and static UI on the server, push 'use client' down to small interactive leaves.

Clarifying questions expected:

  • "Which parts need interactivity or browser APIs?" β€” only those need to be Client Components.
  • "Does anything touch secrets or the database?" β€” keep it on the server with server-only.

Code / implementation expected: Yes β€” a server page composing a client leaf.

  • nextjs
  • rsc
  • server-components
  • client-components

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

5 min read Β· 8 sections

Read the code

A server page composing a small client leaf
// app/products/page.tsx (Server Component)
import "server-only";
import { db } from "@/lib/db";
import AddToCart from "./AddToCart";

export default async function Products() {
  const products = await db.product.findMany();
  return (
    <ul>
      {products.map((p) => (
        <li key={p.id}>
          {p.name} <AddToCart productId={p.id} />
        </li>
      ))}
    </ul>
  );
}

// app/products/AddToCart.tsx (Client Component)
"use client";
import { useState } from "react";
import { addToCart } from "./actions"; // a Server Action
export default function AddToCart({ productId }: { productId: string }) {
  const [added, setAdded] = useState(false);
  return <button onClick={async () => { await addToCart(productId); setAdded(true); }}>{added ? "Added" : "Add"}</button>;
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 21 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextMedium

What is Draft Mode in Next.js and how does it work with a headless CMS?

Continue