Overview

Make every component a Server Component and add "use client" only to the smallest component that needs state, effects, event handlers, or browser APIs. In the Next.js App Router (Next.js 16, React 19.2) this is the default. The common mistake is marking a page or layout "use client" for one interactive child, which pulls the whole subtree into the client bundle.

Comparison

DimensionServer ComponentClient Component ("use client")
JavaScript shippedNone for the component itselfComponent and its dependencies
Data accessawait a database or API in the body; secrets stay server-sideFetch through an API, Server Action, or a query library
Hooks and eventsNo state, effects, or event handlersAll hooks and handlers
Browser APIsNoYes
Props crossing the boundaryMust be serializableReceives serializable props from the server
NestingCan render Client ComponentsCan render Server Components only when passed as children or props

Pick Server Components when

Use a Server Component for anything that only reads data and renders markup.

  • Pages, layouts, data tables, article bodies, and anything that needs a secret or direct database access.
  • Compose: a server ProductPage fetches data and renders a client AddToCart button.
  • In Next.js 16, params, searchParams, cookies(), and headers() are async; await them. Request-time rendering is the default and caching is opt-in through Cache Components and "use cache".

Pick Client Components when

Use a Client Component only for what the browser must run.

  • useState, useReducer, useEffect, useRef, and event handlers.
  • window, localStorage, IntersectionObserver, and client-only libraries (charts, rich-text editors, maps, animation).
  • Forms can stay on the server with Server Actions; only the interactive inputs need the client. See forms.
  • Put the directive in the leaf file. Wrapping third-party client libraries in a small "use client" re-export is cleaner than marking pages.
// app/products/[id]/page.tsx  (Server Component)
import { AddToCart } from "./add-to-cart"; // "use client" lives in this file
 
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  const product = await db.product.find(id);
  return <AddToCart productId={product.id} price={product.price} />;
}

Migrate from the Pages Router

Move route by route. Mark interactive files "use client", move data fetching from useEffect into the server component body, replace next/router with next/navigation, and replace API routes with Server Actions as forms move. See react-server-components for the deeper rules.

FAQ

When should I add “use client” in Next.js?

Add "use client" only to the smallest component that needs state, effects, event handlers, or browser APIs such as window or localStorage. Everything else stays a Server Component, which is the default in the Next.js 16 App Router.

Can a Client Component render a Server Component?

Only when the Server Component is passed in as children or props. A Server Component can render Client Components directly, as long as the props it passes are serializable.

Why is my Next.js client bundle so large?

The common cause is marking a page or layout "use client" for one interactive child, which pulls the whole subtree into the client bundle. Move the directive to the leaf file, or wrap the third-party client library in a small "use client" re-export.

Do forms need to be Client Components?

No; forms can stay on the server with Server Actions, and only the interactive inputs need the client. See forms.