typescriptintermediate
Server Component Composition Patterns
Compose server and client components effectively with the donut pattern and children pass-through.
typescriptPress ⌘/Ctrl + Shift + C to copy
// Pattern 1: The "Donut" Pattern
// Server component wraps client component with server-fetched data
// app/profile/page.tsx (Server Component)
import { ProfileEditor } from './ProfileEditor';
export default async function ProfilePage() {
const user = await getUser(); // Server-side fetch
return (
<div className="max-w-2xl mx-auto">
<h1>Profile</h1>
{/* Pass server data as props to client component */}
<ProfileEditor
initialData={user}
serverRenderedAvatar={
<img src={user.avatar} alt={user.name} className="w-20 h-20 rounded-full" />
}
/>
</div>
);
}
// Pattern 2: Children pass-through
// Client component accepts server component as children
// components/Tabs.tsx
'use client';
import { useState } from 'react';
export function Tabs({
tabs,
}: {
tabs: { label: string; content: React.ReactNode }[];
}) {
const [active, setActive] = useState(0);
return (
<div>
<div className="flex gap-2 border-b">
{tabs.map((tab, i) => (
<button
key={tab.label}
onClick={() => setActive(i)}
className={active === i ? 'border-b-2 border-blue-500' : ''}
>
{tab.label}
</button>
))}
</div>
<div className="p-4">{tabs[active].content}</div>
</div>
);
}
// app/page.tsx (Server Component)
import { Tabs } from '@/components/Tabs';
export default async function Page() {
const posts = await getPosts();
const comments = await getComments();
return (
<Tabs
tabs={[
{
label: 'Posts',
content: <PostList posts={posts} />, // Server Component!
},
{
label: 'Comments',
content: <CommentList comments={comments} />, // Server Component!
},
]}
/>
);
}Use Cases
- interactive layouts
- tabbed content
- modal wrappers
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptadvanced
Server/Client Component Patterns
Correctly compose server and client components with data fetching, interactivity, and composition patterns.
Best for: RSC architecture planning
#nextjs#rsc
typescriptbeginner
Server to Client Component Data Passing
Pass data from server components to client components using props and serialization patterns.
Best for: data hydration
#nextjs#server-components
typescriptadvanced
Middleware Chain Pattern
Compose multiple middleware functions for auth, rate limiting, and geolocation in Next.js middleware.
Best for: Auth guard middleware
#nextjs#middleware
typescriptintermediate
Parallel Data Fetching in Server Components
Fetch multiple data sources in parallel using Promise.all in Next.js server components for faster page loads.
Best for: dashboard pages
#nextjs#data-fetching