Frontend Development

React Server Components, Explained Simply (with Next.js)

React Server Components explained simply — what runs where, when to reach for 'use client', and the traps I hit in production.

Aymane Atigui
Aymane Atigui
·July 24, 2026·7 min read

React Server Components confused me too, and I write Next.js for a living. The docs explain the what; what clicked for me came from shipping them in production — this site included. Here's the explanation I wish I'd read first.

A Server Component runs once, on the server, and ships HTML plus zero JavaScript. A Client Component ships code to the browser. The entire skill is deciding which parts of your page genuinely need to be alive.

The mental model that works

Stop thinking "frontend vs backend". Think of your component tree as mostly dead, selectively alive. A blog article, a product card, a footer — dead: render once on the server, send HTML, done. A search box, a cart button, a form — alive: needs JavaScript in the browser. RSC lets the dead parts cost nothing.

What runs where, concretely

  • Server Component (the default in Next.js App Router): can read the database directly, use secrets, await anything. Ships no JS. Cannot use useState, onClick, or browser APIs.
  • Client Component ("use client" at the top): everything React always was — state, effects, events. Costs bundle size for every line it imports.

The line between them is a one-way door: server can render client children, but a client component can't import a server one (it can receive them as children — the pattern that solves 80% of "how do I…" questions).

The three traps I hit in production

  • The creeping "use client": mark a big component client for one onClick, and everything it imports ships to the browser. Fix: push the directive to the leaves — a tiny <LikeButton>, not the whole article page.
  • Waterfalls: nested awaits render sequentially. Kick off promises together (Promise.all) or pass promises down and use() them.
  • Everything dynamic by accident: one cookies() call opts the route out of static rendering. Isolate the dynamic bits; keep the shell static and cached.

What it means for real projects

This site is a live example: article pages are Server Components reading Postgres directly — no API layer, no client fetch, ~0 JS for content — while the chat widget and admin forms are small client islands. That mix is why the pages are fast, and fast pages are an SEO and cost story, not just a developer preference.

Should you migrate?

New Next.js project: yes, it's the default and the right one. Existing SPA: only page by page, starting with content-heavy routes where the payoff (bundle size, SEO) is biggest. If you want the judgment call made for your codebase — or the migration done — that's my day job.

Topics

ReactNext.jsServer ComponentsPerformance
Aymane Atigui

Aymane Atigui

Software Engineer, Technical Consultant & Product Designer based in Casablanca, Morocco.

Enjoyed this article?

Let's build something together.

Get in Touch