React Server Components
React Server Components (RSC) are React components that run only on the server — at build time or per request — and send their rendered output to the browser as a serialized component tree, without shipping their code or dependencies as JavaScript. They can be async, read directly from databases and files, and keep secrets on the server. Interactive parts of the UI remain Client Components, marked with "use client".
RSC became stable in React 19 and is the default model in the Next.js App Router, with support in other frameworks like React Router and Waku. It changes how you think about React apps: instead of fetching data in the browser after the page loads, most data fetching moves into components that render on the server, and only the interactive islands hydrate in the browser.
TL;DR
- Server Components render only on the server; their code never reaches the browser.
- They can be
asyncand access databases, files, and secrets directly. - Client Components (
"use client") handle state, effects, event handlers, and browser APIs. - Server Components can render Client Components, passing serializable props.
- Server Actions (
"use server") let forms and client code call server functions. - Use
<Suspense>to stream slow parts of the page progressively.
Quick Example
A server component page that queries the database, streams a slow section, and renders an interactive client component:
Core Concepts
RSC vs SSR
Frameworks combine both: the first request gets HTML generated from server and client components, and subsequent navigations fetch RSC payloads.
The Server/Client Boundary
"use client" at the top of a file marks it — and everything it imports — as client code. Rules that follow:
- Server Components can import and render Client Components.
- Client Components can't import Server Components, but can receive them as
childrenor other props. - Props crossing the boundary must be serializable (primitives, plain objects, arrays, Dates, Promises, JSX), not functions or class instances — except Server Actions.
What Goes Where
Server Actions
Functions marked "use server" become endpoints that the client can call. They integrate with <form action={fn}>, useActionState, and useFormStatus for progressive enhancement. Treat every action as a public API endpoint: validate input and check authorization inside it.
Streaming and Suspense
Wrapping slow parts in <Suspense> lets the server send the rest of the page immediately and stream the slow parts as they resolve. Loading states become part of the component tree rather than separate spinners in effects.
Caching
Frameworks cache RSC results and data fetches to avoid repeated work. In Next.js this includes request memoization, the data cache, and full-route caching, controlled by options such as revalidate, revalidatePath, and revalidateTag. Understand your framework's caching defaults before shipping.
Best Practices
Default to Server Components
Add "use client" only where interactivity is needed, and push it as far down the tree as possible so small leaf components hydrate instead of whole pages.
Fetch Data Where It's Used
Colocate queries in the Server Components that render them; frameworks dedupe identical requests within a render.
Avoid Waterfalls
Start independent fetches in parallel (Promise.all) or split them into sibling Suspense boundaries.
Validate and Authorize in Server Actions
Parse inputs with a schema library like Zod and check the user's permissions every time.
Mark Server-Only Modules
Import the server-only package in modules containing secrets so accidental client imports fail at build time.
Common Mistakes
"use client" at the Top of the Tree
Marking a root layout as client turns the entire app into client components, losing RSC benefits.
Passing Functions or Class Instances as Props
Non-serializable props can't cross the boundary. Pass data, or use Server Actions for callbacks.
Leaking Secrets Through Props
Everything passed to a Client Component ends up in the browser. Pass only the fields the UI needs.
Treating Server Actions as Private
They're callable over HTTP by anyone who finds them. Authenticate and validate.
Surprised by Caching
Stale data after mutations usually means a missing revalidation call or misunderstood cache defaults.
FAQ
What are React Server Components?
Components that render exclusively on the server and send a serialized result to the client, so their code and dependencies don't add to the browser's JavaScript bundle.
How are Server Components different from SSR?
SSR renders all components to HTML on the server and then hydrates them all in the browser. Server Components never hydrate; only Client Components ship JavaScript.
Can I use hooks in Server Components?
No. State and effect hooks like useState and useEffect only work in Client Components. Server Components can be async and await data directly.
Do I need Next.js to use Server Components?
You need a framework or bundler integration that supports RSC. Next.js App Router is the most common; React Router, Waku, and others also support it.
Are Server Actions secure?
They're as secure as any API endpoint you write. Frameworks add protections like origin checks, but you must still validate inputs and authorize users inside each action.
Related Topics
- React — The component model RSC extends
- Next.js — The most common RSC framework
- Data Fetching — Client and server data patterns
- Web Performance — Why shipping less JavaScript matters
- SEO for SPAs — Server rendering for discoverability