Skip to content
GeeksSmith
advanced 7 min read

React Server Components (RSC) vs Client Components

React Server Components (RSC) execute exclusively on the server, outputting a lightweight JSON stream without adding any JavaScript to the client bundle. Client Components (`'use client'`) add interactivity and state.

Why it matters in interviews

RSC fundamentally changes frontend architecture by allowing direct database access, eliminating client bundle bloat, and separating data-heavy logic from interactive leaves.

Visual & Interactive Explanation

Server Components vs Client Components

Interactive Comparison

Server Component (Default)

Runs ONLY on server

0 Client JS
ExecutionServer only (build or request)
Client Bundle0 KB JavaScript shipped
Data AccessDirect DB / Filesystem / Secrets
Hooks / Events❌ No useState, useEffect, onClick
Strengths
  • Zero bundle weight
  • Direct database & secret access
Trade-offs
  • No DOM listeners or stateful hooks

Client Component ('use client')

Interactive Leaf Components

Interactive
ExecutionServer (SSR) + Browser (Hydration)
Client BundleJavaScript shipped to browser
Data AccessVia fetch() or props
Hooks / Events✅ Full useState, useEffect, onClick
Strengths
  • Rich user interactivity
  • Access to browser APIs (window, local storage)
Trade-offs
  • Increases client bundle size

Code Examples & Implementation

Passing Server Component as Children to Client Component
// 1. Client Component (Interactive Container)
'use client';
import { useState } from 'react';

export function ExpandableSidebar({ children }: { children: React.ReactNode }) {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
      {/* children is a Server Component, rendered on server with 0 KB client JS! */}
      {isOpen && <aside>{children}</aside>}
    </div>
  );
}

// 2. Server Component (Direct Database Fetcher)
import db from '@/lib/db';
import { ExpandableSidebar } from './ExpandableSidebar';

export default async function Page() {
  const heavyData = await db.analytics.findMany(); // Runs on server only!

  return (
    <ExpandableSidebar>
      <HugeAnalyticsTable data={heavyData} />
    </ExpandableSidebar>
  );
}

Interview-Ready Answers

Server Components run only on the server, outputting a serialized component tree without shipping JS to the browser. Client Components ('use client') run on both server (for initial SSR HTML) and client (for interactivity, hooks, and event listeners).

Official Documentation & Specifications

Follow-up Questions & Deep Dives

Common Mistakes & Anti-Patterns

  • Adding 'use client' at the top of page.tsx instead of isolating interactive buttons to leaf components
  • Trying to access localStorage or window inside a Server Component
  • Passing database connection instances or non-serializable objects across the boundary

Real-World Architectural Scenario

A marketing page uses a 120KB markdown parsing library. If imported into a Client Component, it balloons the client bundle and hurts LCP. How do you fix it with RSC?

Rate Your Readiness

Rate how comfortably you can explain this in an interview to update your global readiness gauge:

Rate your confidence: