React Server Components are the biggest change to React since hooks. They fundamentally alter where your code runs and how data flows through your application.
October 5, 2024 9 min read
# React 19 Server Components Explained
Slug: react-19-server-components-explained
Date: 2024-10-05
Tag: Tech Stack
Meta Description: React Server Components explained for non-experts. What they are, why they matter, and how they change the way you build web applications.
---
React Server Components are the biggest change to React since hooks. They fundamentally alter where your code runs and how data flows through your application.
Most explanations focus on the technical details. This post explains what Server Components mean for people building products—why they exist, what problems they solve, and how to think about them without getting lost in implementation details.
If you're a founder, product manager, or developer new to Server Components, this is written for you.
The Core Idea in Plain English
Traditional React components run in the browser. Your user's device downloads JavaScript, executes it, and renders the interface.
Server Components run on the server. The server executes the component, generates HTML, and sends that HTML to the browser. The JavaScript never reaches the user's device.
Why does this matter?
Less JavaScript shipped: Components that only render don't need to be downloaded
Direct database access: Server code can query databases without API routes
Stop planning and start building. We turn your idea into a production-ready product in 6-8 weeks.
Better security
Faster initial load: HTML arrives ready to display
The mental model: some parts of your interface are static once rendered—headers, footers, static content. These don't need interactivity. Server Components let you keep that code on the server where it belongs.
Before and After: A Practical Example
Consider a product page that displays product details and reviews.
Waterfall requests: Data fetches happen after JavaScript loads
Loading states: User sees spinner while waiting
Duplicate code: API routes just forward database queries
Large bundle: All components ship to browser
With Server Components
typescript
// This runs on the server
async function ProductPage({ productId }) {
const product = await db.products.find(productId);
const reviews = await db.reviews.findByProduct(productId);
return (
<div>
<ProductDetails product={product} />
<ReviewList reviews={reviews} />
<ReviewForm productId={productId} />
</div>
);
}
The improvements:
No loading state: HTML arrives with data already embedded
No API routes: Server component queries database directly
Smaller bundle: ProductDetails and ReviewList don't ship as JavaScript
Faster display: User sees content immediately
The ReviewForm component (which needs interactivity) would be marked as a Client Component and still work as traditional React.
Server vs. Client Components
React 19 introduces a clear distinction:
Server Components (Default)
Run only on the server
Can access databases, file systems, environment variables
Cannot use useState, useEffect, or browser APIs
Cannot handle clicks, form inputs, or other interactions
Never ship JavaScript to the browser
Client Components
Run in the browser (and may also render on server for initial HTML)
Use useState, useEffect, and browser APIs
Handle user interactions
Ship JavaScript to the browser
Marked with 'use client' directive at the top of the file
The Mental Model
Think of Server Components as templates that produce HTML. They can include Client Components for interactive pieces, but the Server Component itself just generates markup.
javascript
Server Component (ProductPage)
├── Server Component (ProductDetails) → Just HTML
├── Server Component (ReviewList) → Just HTML
└── Client Component (ReviewForm) → HTML + JavaScript
Only the ReviewForm needs JavaScript in the browser. Everything else is pure HTML.
Why This Matters for Startups
Server Components solve problems that particularly affect startup products.
Faster Initial Page Load
First impressions matter. Users judge your product in seconds. Server Components eliminate the loading spinner for initial content.
Traditional React:
Download HTML shell
Download JavaScript bundle
Execute JavaScript
Fetch data from API
Render content
With Server Components:
Download HTML with content
The difference is measurable. Pages load 40-60% faster in many cases.
SEO Without Complexity
Server-rendered content is indexable by search engines. With Server Components, SEO-friendly rendering is the default, not a special configuration.
Marketing pages, blog content, product listings—anything that needs to rank in search results—works correctly without additional setup.
Reduced Infrastructure
Server Components eliminate many API routes. If a component just needs to display data from your database, it can query directly.
Fewer API routes means:
Less code to maintain
Fewer potential security vulnerabilities
Simpler architecture
Faster development
Better Mobile Performance
Mobile networks are slow. Large JavaScript bundles take time to download and parse. Server Components reduce bundle size by keeping non-interactive code on the server.
For users on 3G connections or older devices, this can mean the difference between a usable product and one that feels broken.
Common Questions and Misconceptions
"Do Server Components replace Client Components?"
No. Server Components handle static rendering. Client Components handle interactivity. Most applications need both.
A dashboard might be 80% Server Components (data display) and 20% Client Components (forms, filters, real-time updates).
"Is this the same as server-side rendering?"
Related but different. Server-side rendering (SSR) runs client components on the server for initial HTML, then "hydrates" them in the browser.
Server Components never run in the browser at all. No hydration, no JavaScript shipped.
SSR: Render on server → Send HTML + JavaScript → Hydrate in browser
Server Components: Render on server → Send HTML only
"Can Server Components use React state?"
No. Server Components run once on the server and produce HTML. There's no persistent runtime to hold state.
If you need state, use a Client Component for that piece of the UI.
"What about real-time updates?"
Server Components render once. For real-time updates, you need Client Components that subscribe to data changes.
Our approach with Convex: use Server Components for initial page structure, Client Components with Convex queries for data that updates in real-time.
"Do I need to rewrite my existing React app?"
No. Server Components are additive. You can adopt them incrementally, converting components as it makes sense.
Existing Client Components continue working. You add Server Components where they provide value.
How Server Components Work in Next.js
Next.js 14+ uses Server Components by default in the App Router.
File-Based Conventions
javascript
app/
├── layout.tsx # Server Component by default
├── page.tsx # Server Component by default
├── loading.tsx # Loading UI
└── components/
├── Header.tsx # Server Component by default
└── Form.tsx # Add 'use client' for interactivity
Marking Client Components
typescript
"use client";
import { useState } from "react";
export function ContactForm() {
const [email, setEmail] = useState("");
// ... interactive form logic
}
The 'use client' directive marks this component and its imports as client-side code.
Data Fetching
Server Components can be async and fetch data directly:
Authentication checks: Protecting routes based on session
Use Client Components For
Forms with validation: Real-time field validation
Interactive elements: Dropdowns, modals, tooltips
State management: Shopping carts, filters, preferences
Real-time features: Live updates, notifications
Browser APIs: Geolocation, camera, localStorage
The 80/20 Rule
Most applications end up with roughly 80% Server Components and 20% Client Components. The interactive pieces are important but usually aren't the majority of your UI.
If you find yourself marking everything as Client Components, you're probably not getting the Server Component benefits. Step back and identify what actually needs interactivity.
Performance Impact
We've measured the impact on several MVP projects:
Bundle Size Reduction
Typical Next.js app with traditional React: 150-300KB JavaScript
Same app with Server Components: 50-100KB JavaScript
The reduction depends on how much of your UI is static. Content-heavy sites see larger improvements.
Time to First Contentful Paint
Traditional React: 1.5-3 seconds
Server Components: 0.5-1.5 seconds
The improvement comes from HTML arriving with content, rather than JavaScript downloading, parsing, and fetching data.
SEO Metrics
Server-rendered content is immediately indexable. No "please wait for JavaScript" issues with search engine crawlers.
Core Web Vitals (particularly LCP and CLS) typically improve because content appears faster and doesn't shift during hydration.
Common Mistakes to Avoid
Mistake 1: Making Everything a Client Component
When in doubt, developers add 'use client'. This defeats the purpose.
Default to Server Components. Only add 'use client' when you actually need interactivity.
Mistake 2: Fetching Data in Client Components
If data doesn't need to update in real-time, fetch it in a Server Component:
typescript
// Wrong: Client Component fetching static data
'use client';
function ProductList() {
const [products, setProducts] = useState([]);
useEffect(() => {
fetch('/api/products').then(/* ... */);
}, []);
// ...
}
// Right: Server Component with direct access
async function ProductList() {
const products = await db.products.list();
return products.map(p => <ProductCard key={p.id} product={p} />);
}
Mistake 3: Passing Functions to Client Components
Server Components can't pass functions as props to Client Components:
typescript
// This won't work
async function Page() {
const handleClick = () => console.log('clicked');
return <Button onClick={handleClick} />; // Error
}
Server Components run once on the server. Functions can't be serialized and sent to the browser.
Use Server Actions for server-side logic triggered by client events.
Mistake 4: Ignoring Suspense Boundaries
Without Suspense, slow data blocks the entire page:
No client-side redirect flash. The server handles authentication before any HTML reaches the browser.
Key Takeaways
React Server Components change how web applications are built:
Server Components render on the server only. No JavaScript shipped for static content.
Client Components handle interactivity. Use them for forms, real-time features, and browser APIs.
Most UI should be Server Components. Default to server, add client when needed.
Performance improves significantly. Smaller bundles, faster initial load, better SEO.
The mental model takes adjustment. Think about where code runs when writing components. For end-to-end type safety with Server Components, see TypeScript Full-Stack: End-to-End Type Safety.
For MVPs, Server Components mean faster-loading products with less code. The learning curve is worth it for the performance and simplicity gains.
---
At NextBuild, we build MVPs with React 19 Server Components, Next.js, and Convex. If you're planning a web application and want modern architecture from day one, let's discuss your project.
Learn how to create a basic version of your product for your new business.