Topic 20 of 39
Component Composition
Overview
A core pattern in Next.js is interleaving Server and Client Components. You cannot import a Server Component directly into a Client Component, but you CAN pass a Server Component as a child or prop to a Client Component. This keeps heavy logic on the server.
Syntax
tsx
// ServerComponent.tsx
export default async function DataList() {
const data = await db.fetch();
return <ul>{/* render data */}</ul>;
}
// ClientWrapper.tsx
'use client';
export default function ClientWrapper({ children }) {
const [open, setOpen] = useState(false);
return (
<div>
<button onClick={() => setOpen(!open)}>Toggle List</button>
{open && children}
</div>
);
}
// page.tsx (Server Component)
export default function Page() {
return (
<ClientWrapper>
{/* We pass the Server Component as 'children' */}
<DataList />
</ClientWrapper>
);
}Common Pitfalls
- Importing a Server Component directly inside a file with
'use client'. It silently becomes a Client Component, losing all server benefits. - Passing large, complex, non-serializable objects (like classes or functions) as props from Server to Client.
Interview Questions
Q:
How do you safely render a Server Component inside a Client Component?
A:
By using composition. You pass the Server Component as a prop (usually children) from a parent Server Component into the Client Component.
Real-World Example
An interactive layout (Client) wrapping static SEO content (Server).
example
tsx
// The composition pattern allows you to keep 'use client'
// as far down the tree as possible, maximizing Server Component usage.Check Your Knowledge
Test your understanding of Component Composition with these quick questions.