React: Server Components (RSC) vs Client Components
With the release of React 18 and frameworks like the Next.js App Router, the React ecosystem underwent its biggest architectural shift since Hooks: React Server Components (RSC).
What are React Server Components, and how do they differ from traditional Client Components?
This is a guaranteed interview question for any modern React role, testing your understanding of network boundaries and rendering paradigms.
1. Traditional Client Components
Historically, all React components were Client Components. Whether your app used Client-Side Rendering (CSR) or traditional Server-Side Rendering (SSR), the end result was the same: the component's JavaScript code was bundled, sent to the browser, and executed on the client machine to provide interactivity.
Because they run in the browser, Client Components:
- Have access to state (
useState,useReducer). - Have access to lifecycle hooks and side effects (
useEffect). - Can listen to DOM events (
onClick,onChange). - Have access to browser APIs (
window,localStorage).
2. React Server Components (RSC)
Server Components are a new paradigm where components run exclusively on the server during the build or request phase. They are never sent to the browser.
The server evaluates the component, fetches any required data natively, and sends a special serialized representation (similar to JSON) of the UI to the browser. The browser then seamlessly merges this UI with the interactive Client Components.
Because they run exclusively on the server, Server Components:
- Cannot use state or effects (No
useStateoruseEffect). - Cannot use event listeners (No
onClick). - Can securely access backend resources directly (Databases, File Systems, private API keys).
- Ship ZERO JavaScript to the client bundle.
The Syntax (use client)
In Next.js App Router, all components are Server Components by default.
If you need interactivity (state, clicks, effects), you must explicitly mark a file as a Client Component by placing the "use client" directive at the very top of the file.
// This is a Server Component (Default)
// It accesses the database securely and ships zero JS!
import db from '@/lib/db';
export default async function UserProfile({ userId }) {
// Await the data natively! No useEffect required!
const user = await db.user.find(userId);
return <h1>{user.name}</h1>;
}// This is a Client Component (Opt-in)
"use client";
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}3. The Composition Rule (The Boundary)
The most important rule to understand is the Network Boundary.
Server Components CAN import and render Client Components. This is how you pass data from the server down to an interactive UI.
Client Components CANNOT import Server Components. Once you cross the boundary into a "use client" file, everything imported beneath it also becomes part of the client bundle.
Note: You can pass a Server Component as a children prop into a Client Component, which is a common pattern to bypass this restriction.
Senior-Level Interview Answer
React Server Components (RSC) represent a fundamental shift in React's rendering architecture by splitting the component tree across the server-client network boundary. Server Components execute exclusively on the server, enabling secure, direct access to backend infrastructure (like databases) while shipping zero JavaScript to the client bundle, drastically improving TTI (Time to Interactive) and overall bundle size. Because they do not hydrate on the client, they lack access to state, lifecycle hooks, and DOM events. Conversely, traditional Client Components—opted into via the
"use client"directive—execute in the browser and handle all interactivity and client-side state. The modern best practice is to compose applications with Server Components at the trunk of the tree to handle data fetching, passing the resulting data as props to interactive Client Components at the leaves.
Common Interview Mistakes
❌ Confusing RSC with traditional SSR (Server-Side Rendering)
This is the most common trap!
- SSR (Server-Side Rendering): The server renders the initial HTML to get pixels on the screen quickly. However, the exact same React component code is still downloaded to the browser, where it "hydrates" to become interactive.
- RSC (Server Components): The component code stays on the server permanently. It is never downloaded, and it never hydrates. Modern Next.js utilizes both: Client Components are SSR'd for initial load and then hydrated, while Server Components are processed completely server-side.
