- Next.js
- Server Components & Boundaries
- The "use client" Boundary: What Crosses the Wire?
The "use client" Boundary: What Crosses the Wire?
The "use client" directive marks an entry point to the client bundle boundary, not code that executes exclusively in the browser. Client components still pre-render to HTML on the server during SSR. All props passed from Server Components to Client Components must be serializable (JSON-like), prohibiting functions, classes, and Symbol keys.
Learning Objectives
Understand that "use client" defines a module boundary rather than client-only execution.
Identify serializable versus non-serializable props crossing the boundary.
Explain the serialization error thrown when passing event handlers or class instances.
Analyze how the bundler creates separate server and client chunks based on directives.
Prerequisites & Background Knowledge
Why Interviewers Care
Essential foundational knowledge tested in both screening and live coding rounds.
The Challenge
What does the "use client" directive actually declare in Next.js? What types of props can and cannot cross the Server-to-Client component boundary?
Code Architecture & Implementation
1// 1. SERVER COMPONENT2import { UserProfileModal } from './UserProfileModal';34export default async function Page() {5 const user = {6 id: 'u-123',7 name: 'Alice Developer',8 role: 'Staff Engineer',9 createdAt: new Date(), // Date objects serialize to ISO strings across boundary10 };1112 // VALID PROPS: primitives, plain objects, arrays, Dates, BigInts, JSX elements13 // INVALID PROPS: Functions, class instances, Symbols14 return (15 <div>16 <UserProfileModal17 user={user}18 // ❌ RUNTIME ERROR: Event handlers cannot cross the RSC boundary!19 // onSave={() => console.log('Saved')}20 />21 </div>22 );23}2425// 2. CLIENT COMPONENT BOUNDARY26'use client';2728export function UserProfileModal({ user }: { user: any }) {29 // Can use client hooks here30 return <div>{user.name} ({user.role})</div>;31}
Architectural Explanation
The "use client" Contract
- Module Boundary: When Next.js encounters
"use client"at the top of a file, it treats that module and all its imports as part of the client component tree. - Server Execution Still Occurs: Client Components are still rendered to HTML on the server during initial page load for fast visual delivery.
"use client"merely tells the bundler: "Include this module in the client JavaScript bundle so it can hydrate and become interactive." - Serialization Boundary: Because Server Components render on the server and Client Components hydrate in the browser, any prop passed from a Server Component to a Client Component must be serialized into the React Flight protocol stream:
- Allowed: Strings, numbers, booleans, null, undefined, plain objects, arrays, Dates, BigInts, and React elements (JSX).
- Prohibited: JavaScript functions, methods, class instances (with prototypes), and non-standard symbols.
- Exception: Server Actions marked with
"use server"can be passed as callable function references.
Common Mistakes & Anti-Patterns
Placing "use client" at the top of every file in the project, reverting Next.js to an old SPA architecture.
Passing an onClick or onSubmit callback prop from a Server Component to a Client Component.
Assuming "use client" means code will never execute on the server.
Interview Follow-Up Traps
Interviewer asks: "Can you pass a Date object from a Server Component to a Client Component?" Trap answer: No, only JSON. Correct answer: Yes! React Flight natively serializes Date instances, converting them back to Date objects on the client.
Interviewer asks: "Can you pass a Server Action from a Server Component to a Client Component?" Trap answer: No, functions cannot cross the boundary. Correct answer: Yes! Server Actions defined with "use server" serialize as RPC endpoint IDs and can be passed as function props.
Frequently Asked Questions
Do all files imported by a "use client" file need the "use client" directive?
No. Once a boundary is declared, all modules imported down that dependency branch automatically become client components.
What is the performance consequence of adding "use client" too high up the tree?
It includes all child modules in the client JavaScript bundle, inflating bundle size and delaying hydration.
How do you keep client bundles small?
Push "use client" boundaries down to the leaf nodes of your component tree.
Can a Client Component render a Server Component?
Yes, but only by receiving the Server Component as children or a JSX prop from an outer Server Component.
