React developers, rejoice! React Server Components (RSC) represent the biggest architectural shift in React since Hooks. Yet the mental model remains a source of confusion. Let's build a clear picture of what runs where, why it matters, and how to use RSC effectively in 2026.
The Core Idea: Components That Never Ship to the Client:
A Server Component runs only on the server and never sends its code to the browser. Its output is serialized React elements, a description of the UI, not the component itself. This means zero JavaScript cost for the component's logic.
Link to section: 1. The Default is Server1. The Default is Server
In the App Router, every component is a Server Component by default. No directive needed:
// app/page.tsx: this is a Server Component
import { db } from '@/lib/db';
export default async function Page() {
// Direct database access, no API route needed
const posts = await db.post.findMany();
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
No fetch, no useEffect, no client-side data fetching. The database query runs on the server, and only the rendered HTML ships to the client.
Link to section: 2. Opting Into the Client with ,[object Object]2. Opting Into the Client with 'use client'
When you need interactivity (state, effects, event handlers), add the 'use client' directive:
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
The 'use client' directive marks the boundary: everything imported into this file (and its imports) becomes part of the client bundle.
Link to section: 3. The Composition Pattern3. The Composition Pattern
Server and Client Components compose freely, but with a rule: Server Components can pass serializable props to Client Components, but not functions or non-serializable values:
// Server Component
import { LikeButton } from './like-button';
export default function Post({ post }) {
return (
<article>
<h1>{post.title}</h1>
<p>{post.body}</p>
{/* Pass serializable props */}
<LikeButton postId={post.id} initialLikes={post.likes} />
</article>
);
}
// Client Component
'use client';
import { useState } from 'react';
export function LikeButton({ postId, initialLikes }) {
const [likes, setLikes] = useState(initialLikes);
return (
<button onClick={() => setLikes(likes + 1)}>
{likes} likes
</button>
);
}
Link to section: 4. Children as the Escape Hatch4. Children as the Escape Hatch
You can't pass a Server Component as a prop directly to a Client Component, but you can pass it as children:
// Client Component wrapper
'use client';
export function ClientWrapper({ children }) {
const [open, setOpen] = useState(false);
return (
<div>
<button onClick={() => setOpen(!open)}>Toggle</button>
{open && children}
</div>
);
}
// Server Component using the wrapper
import { ClientWrapper } from './client-wrapper';
import { db } from '@/lib/db';
export default async function Page() {
const data = await db.query('SELECT * FROM posts');
return (
<ClientWrapper>
{/* This Server Component renders on the server */}
<ServerList items={data} />
</ClientWrapper>
);
}
The children prop is serialized as React elements and rendered on the server, while the ClientWrapper handles the interactive toggle on the client.
Link to section: 5. When to Use Which5. When to Use Which
| Need | Use |
|---|---|
| Fetch data, access backend | Server Component |
| Static content, no interactivity | Server Component |
useState, useEffect, event handlers | Client Component |
Browser APIs (window, document) | Client Component |
| Heavy client-side libraries | Client Component (lazy load) |
Embrace a New Era of React Architecture:
React Server Components fundamentally change how we build React apps, moving logic to the server and shipping less JavaScript. By understanding the boundary between server and client, you can build faster, more maintainable applications.
React Docs: Server Components
Start building with RSC and rethink what runs where in your React applications!