DEV3 Technologies home

DEV3 Developer Forum

What is the difference between server and client components in the Next.js App Router?

Next.js helpSolved0 views
dev3 ·

I am moving a project to the Next.js 15 App Router. Every file seems to be a server component by default, but when I add useState I get an error. When should I use "use client" and what actually changes?

#nextjs#react#app-router

0

1 reply

dev3 · Accepted answer

Short version: in the App Router every component is a React Server Component (RSC) unless the file (or a file that imports it) starts with "use client".

Server components

  • Render only on the server; their code is not shipped to the browser.
  • Can be async, read databases, files and secrets directly.
  • Cannot use useState, useEffect, event handlers or browser APIs.

Client components

  • Marked with "use client" at the top of the file.
  • Still pre-rendered to HTML on the server, then hydrated in the browser.
  • Needed for state, effects, event handlers, window, and most interactive libraries.
// app/products/page.tsx (server)
import { db } from "@/lib/db";
import AddToCart from "./add-to-cart";

export default async function Page() {
  const products = await db.product.findMany();
  return products.map((p) => (
    <div key={p.id}>
      {p.name} <AddToCart id={p.id} />
    </div>
  ));
}
// app/products/add-to-cart.tsx
"use client";
import { useState } from "react";
export default function AddToCart({ id }: { id: string }) {
  const [n, setN] = useState(0);
  return <button onClick={() => setN(n + 1)}>Add ({n})</button>;
}

Rules of thumb

  1. Keep "use client" as low in the tree as possible (a small button, not the whole page).
  2. A client component can render server components only when they are passed as children or props, not imported inside it.
  3. Props crossing the boundary must be serialisable (plain objects, arrays, strings, numbers, Date, Map/Set and Promises are fine; class instances and functions are not, except Server Actions).
  4. Code that must never reach the browser can import server-only.

Pitfall: putting "use client" in a layout makes everything it imports client code, which hurts bundle size.

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.