← Back to all posts
·7 min read

React Server Components Explained Simply

React

React Server Components (RSC) are the biggest shift in React since hooks. But the docs make it sound more complicated than it is. Let me break it down.

The Core Idea

There are now two types of React components:

  1. Server Components — run on the server, return HTML, ship zero JS
  2. Client Components — run in the browser, handle interactivity

By default, every component in the Next.js App Router is a Server Component.

When to Use "use client"

Add "use client" at the top of a file only when you need:

  • useState, useEffect, or any React hook
  • Browser APIs (window, document, localStorage)
  • Event handlers (onClick, onChange)
  • Third-party libraries that use browser APIs
"use client";

import { useState } from "react";

export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}

The Mental Model

Think of it like this:

  • Server Components = your HTML template engine (like PHP, Jinja, EJS)
  • Client Components = the interactive sprinkles on top

The page is mostly server-rendered HTML. Only the parts that need interactivity get hydrated with JavaScript.

Common Mistakes

1. Making everything a Client Component

Don't add "use client" to every file. Keep the boundary as low as possible in the component tree.

2. Passing server data through client boundaries wrong

You can pass serializable props from Server to Client components, but not functions, classes, or Dates.

// Server Component
import { LikeButton } from "./LikeButton"; // Client Component

export default async function Post({ id }: { id: string }) {
  const post = await getPost(id);
  // Pass serializable data only
  return <LikeButton postId={post.id} initialLikes={post.likes} />;
}

3. Trying to use async in Client Components

Only Server Components can be async. If you need to fetch data in a Client Component, use useEffect or a library like SWR/TanStack Query.

The Payoff

Once you get the mental model right, RSC lets you build apps that are:

  • Faster — less JavaScript shipped to the browser
  • Simpler — no need for an API layer for read operations
  • More secure — sensitive logic stays on the server

It took me a few projects to fully internalize this pattern. But now I can't imagine building React apps any other way.