Loading lessons...
Interleaving Server and Client Components
To build performant Next.js applications, you must know how to compose Server Components and Client Components together without breaking the RSC boundary.
Rule #1: You CANNOT import a Server Component into a Client Component
If a file marked with 'use client' directly imports a Server Component file, that component will be forcibly converted into a Client Component!
tsx
// ❌ WRONG PATTERN
'use client';
// HeavyServerList will be bundled for the client!
import HeavyServerList from './HeavyServerList';
export default function ClientContainer() {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
{isOpen && <HeavyServerList />}
</div>
);
}
Rule #2: Pass Server Components as children or Props
To render a Server Component inside a Client Component, pass the Server Component as a React node prop (such as children) from an overarching Server Component!
tsx
// ✅ CORRECT PATTERN - Client Component acts as a wrapper slot
// components/ClientModal.tsx
'use client';
import { useState } from 'react';
export default function ClientModal({ children }: { children: React.ReactNode }) {
const [open, setOpen] = useState(true);
return (
<div className="relative">
<button onClick={() => setOpen(!open)}>Toggle Modal</button>
{open && <div className="p-4 border shadow-lg">{children}</div>}
</div>
);
}
// app/page.tsx - Server Component composition root
import ClientModal from '@/components/ClientModal';
import HeavyServerList from '@/components/HeavyServerList';
export default async function Page() {
return (
<main>
<h1>Dashboard Page</h1>
{/* HeavyServerList remains a pure Server Component! */}
<ClientModal>
<HeavyServerList />
</ClientModal>
</main>
);
}
Serialization Boundary Rules
When passing props from a Server Component to a Client Component, the prop values must be serializable across the network boundary.
| Allowed Prop Types (Serializable) | Disallowed Prop Types |
|---|---|
| Strings, Numbers, Booleans | Functions (onClick={() => ...}) |
| Objects & Arrays (plain) | Class Instances |
null & undefined | Symbols & Unserializable closures |
JSX Elements (via children slot) | Complex Streams / File Handles |
TL;DR
- Never import a Server Component directly inside a
'use client'module. - Pass Server Components as
childrenor JSX props to Client Components. - Data passed as props across the Server-to-Client boundary must be serializable JSON-like data.
- Keep Client Components at the visual leaves of your component tree.