React

React Server Components Explained: What They Are and When to Use Them

A practical, no-hype breakdown of React Server Components — what problem they solve, how they differ from Client Components, and when you actually need them.

Ava ChenJune 2, 2026 (updated July 10, 2026)3 min read
Share:

React Server Components (RSCs) changed how the React team thinks about rendering — but the concept is often explained in a way that's more confusing than it needs to be. Here's the practical version.

The problem RSCs solve

Before Server Components, a typical React app shipped one thing to the browser: JavaScript. Every component — even ones that only fetched data and rendered static markup — had to be bundled, downloaded, and hydrated on the client.

That's wasteful for components that never need interactivity. A blog post body, a product description, a footer — none of that needs to run in the browser at all.

Server Components let you write components that:

  • Run only on the server (or at build time, in a static export)
  • Never ship their JavaScript to the client
  • Can directly access server-only resources (the filesystem, environment secrets, databases) without an API layer

Server vs. Client Components

tsx
// app/components/PostBody.tsx — Server Component (default)
export default async function PostBody({ slug }: { slug: string }) {
  const post = await getPostBySlug(slug); // runs on the server / at build time
  return <article dangerouslySetInnerHTML={{ __html: post.html }} />;
}
tsx
// app/components/LikeButton.tsx — Client Component
"use client";
 
import { useState } from "react";
 
export default function LikeButton() {
  const [liked, setLiked] = useState(false);
  return <button onClick={() => setLiked(!liked)}>{liked ? "Liked" : "Like"}</button>;
}

The "use client" directive is the boundary. Everything below it (and its imports) gets bundled for the browser. Everything without it stays on the server.

When to reach for each

Use a Server Component when...Use a Client Component when...
You're fetching dataYou need useState or useEffect
The content is static per requestYou're attaching event listeners
You want zero client JS for that pieceYou depend on browser-only APIs

A common mistake

A frequent anti-pattern is slapping "use client" on a top-level layout "just to be safe." That drags every child component into the client bundle, even ones that didn't need it. Push "use client" as far down the tree as possible — ideally onto small, leaf components like a button or a form.

Static export and Server Components

In a fully static export (output: "export"), Server Components still work exactly as described — they just run once, at build time, instead of per-request. The output is plain HTML, so there's no runtime cost at all for visitors.

That's the sweet spot for a content site like this one: nearly everything is a Server Component, and "use client" is reserved for the handful of pieces that truly need interactivity — theme toggles, search boxes, and copy buttons.

Advertisement

Frequently Asked Questions

Ava Chen
Ava Chen

Senior Software Engineer

Ava writes about frontend architecture, React, and TypeScript. Previously built developer tools at scale-up startups.

Related Articles