Client Components are how you add interactivity — state, effects, event handlers, and browser APIs — inside the App Router. This lesson covers the "use client" directive and best practices for keeping client bundles small.
Opting In with "use client"
Adding the literal string "use client" as the very first line of a file marks every component in that file (and everything it exclusively imports into the client bundle) as a Client Component. Client Components render once on the server for the initial HTML (like any component), then hydrate in the browser, attaching event listeners and enabling hooks like useState and useEffect.
The directive applies at the module boundary: once a file is marked "use client", every component defined in that file is a Client Component, and Next.js includes it (and its dependencies) in the client-side JavaScript bundle.
Without "use client" at the top, this file would fail to build — useState and onClick are not allowed in Server Components.
Where the Directive Goes
"use client"; // must be the very first line, before any imports
import { useState } from "react";
// ... rest of the file
The directive must be the literal first line of the file, before any imports.
It applies to the whole file — you cannot mark just one function in a multi-component file as client-only.
Once a component is a Client Component, everything it renders is also part of the client bundle by default (unless it receives Server Components as children).
Client Components can still be rendered on the server for the initial HTML — "client" describes where they can run, not where they exclusively run.
Client Components Cheat Sheet
What requires opting in with "use client".
Feature
Requires "use client"?
useState, useReducer
Yes
useEffect, useLayoutEffect
Yes
Event handlers (onClick, onChange)
Yes
Browser APIs (window, localStorage)
Yes
Third-party hooks/libraries built on React state
Usually yes
Rendering static, non-interactive JSX
No
Pushing "use client" as Far Down as Possible
A common mistake is marking an entire page (or a large layout) as a Client Component just because one small button needs onClick. Instead, extract that button into its own tiny Client Component and keep everything else — including the surrounding page — as a Server Component.
Only AddToCartButton.tsx ships as client JavaScript; the data fetching and list rendering stay entirely on the server.
Props Must Be Serializable
When a Server Component passes props to a Client Component, those props are serialized and sent across the server/client boundary, similar to JSON.stringify. This means functions, class instances, and other non-serializable values cannot be passed directly (with the notable exception of Server Actions, covered in a later lesson, which use a special mechanism).
Common Mistakes
Marking a large layout or page as a Client Component to fix one small interactive element.
Forgetting the directive must be the very first line, before any import statements.
Trying to pass a non-serializable prop (like a database client instance) from a Server to a Client Component.
Assuming a Client Component never runs on the server — it still renders server-side for the initial HTML.
Key Takeaways
"use client" at the top of a file opts every component in it into being a Client Component.
Client Components enable hooks, event handlers, and browser APIs.
Push "use client" down to the smallest component that actually needs interactivity.
Props from Server to Client Components must be serializable.
Client Components still render on the server initially; the directive controls capability, not execution location exclusively.
Pro Tip
Think of "use client" as marking a boundary, not a whole subtree — a Client Component can still receive Server Components as children, so you can wrap interactive shells (like a modal or dropdown) around server-rendered content without converting that content into client JavaScript.
You now understand both component types. Next, learn how to build shared components that work well across Server and Client boundaries.