React server components (rsc)
What are React Server Components?
React Server Components (RSC) are components that execute only on the server. They never run in the browser, never ship JavaScript to the client, and can directly access server-side resources (databases, file system, APIs).
Server vs Client Components
// Server Component (default in Next.js App Router)
// β
No "use client" directive β runs on server
async function UserProfile({ userId }: { userId: string }) {
// Direct database access β no API needed!
const user = await db.query.users.findFirst({
where: eq(users.id, userId)
});
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
<LikeButton userId={userId} /> {/* Client Component */}
</div>
);
}// Client Component β "use client" directive required
"use client";
import { useState } from "react";
function LikeButton({ userId }: { userId: string }) {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked(!liked)}>
{liked ? "β€οΈ Liked" : "π€ Like"}
</button>
);
}Key Differences
| Feature | Server Component | Client Component |
|---|---|---|
"use client" directive | No | Yes |
| Runs on | Server only | Server (SSR) + Client |
| JS bundle size | Zero (not sent to client) | Included in JS bundle |
useState, useEffect | β Cannot use | β Can use |
| Event handlers (onClick) | β Cannot use | β Can use |
| Async component | β Can be async | β Cannot be async |
| Access DB/filesystem | β Directly | β Via API only |
| Access browser APIs | β No window/document | β Full access |
Composition Rules
Server Component β can render Server or Client components β
Client Component β can render ONLY Client components β
Client Component β can accept Server Component as children (via props) β
// β
Passing Server Component as children to Client Component
// layout.tsx (Server Component)
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<ClientSidebar>
{children} {/* children can be Server Components */}
</ClientSidebar>
);
}Benefits
1. Zero Bundle Size
Server Components don't add JavaScript to the client bundle. Heavy libraries used only for rendering (e.g., syntax highlighting, markdown parsing) stay on the server:
// Server Component β marked library stays on server
import { marked } from "marked"; // NOT sent to client
import hljs from "highlight.js"; // NOT sent to client
async function BlogPost({ slug }: { slug: string }) {
const post = await getPost(slug);
const html = marked(post.content); // Processed on server
return <article dangerouslySetInnerHTML={{ __html: html }} />;
}2. Direct Data Access
// No API routes needed β query directly
async function ProductList() {
const products = await db.select().from(productsTable);
return (
<ul>
{products.map(p => (
<li key={p.id}>{p.name} β ${p.price}</li>
))}
</ul>
);
}3. Streaming and Suspense
import { Suspense } from "react";
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<Skeleton />}>
<SlowDataComponent /> {/* Streams when ready */}
</Suspense>
</div>
);
}When to Use Which
| Use Server Component when | Use Client Component when |
|---|---|
| Fetching data | Using state (useState) |
| Accessing backend resources | Using effects (useEffect) |
| Keeping sensitive data on server | Using event listeners (onClick) |
| Reducing client JS bundle | Using browser APIs |
| Heavy dependencies (markdown, etc.) | Using custom hooks with state |
Important:
React Server Components fundamentally change how we build React apps. Server Components run only on the server, have zero client JS cost, and can access backend resources directly. Use them for data fetching and rendering; use Client Components only when you need interactivity (state, events, browser APIs). They're the default in Next.js App Router.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.