React  

What are React Server Components and How to Migrate?

Introduction

React Server Components (RSCs) are among the most significant updates introduced in modern React. They allow developers to run components on the server rather than in the browser, resulting in faster applications, smaller bundles, and better performance. If you are coming from older versions of React or traditional client-side rendering, the concept may feel new. This article explains RSC in simple, easy-to-understand words and also guides you step-by-step on how to migrate your existing application to the latest version of React.

What Are React Server Components?

React Server Components are components that run only on the server. They never ship JavaScript to the browser. Instead, the server sends lightweight HTML and serialized data to the client.

Key Features

  • Run on the server, not the browser.

  • Never included in the client-side JavaScript bundle.

  • Can securely access server-only resources (DB, files, API keys).

  • Reduce bundle size → faster load time.

  • Improve SEO automatically.

  • Designed for modern full-stack frameworks.

How React Server Components Work

RSC uses a hybrid rendering model:

  • Some components run on the server (Server Components).

  • Some run on the client (Client Components).

  • React decides how to combine them efficiently.

Server Component Example

// This file can be a server component by default

import db from "./db";

export default async function ProductList() {
  const products = await db.getProducts();
  return (
    <ul>
      {products.map(p => <li key={p.id}>{p.name}</li>)}
    </ul>
  );
}
  • Runs on the server

  • Fetches database directly

  • Sends HTML to client

Client Component Example

"use client";

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}
  • Runs in the browser

  • Needed for interactivity

Server vs Client Components: Quick Comparison

FeatureServer ComponentsClient Components
Runs onServerBrowser
JS bundleNoYes
Access DBYesNo
SEOExcellentDepends
InteractivityNoYes

Benefits of React Server Components

1. Smaller JavaScript Bundle Size

Since server components do not ship JS to the client, bundle size is much smaller.

2. Better Performance

  • Less hydration work in the browser

  • Faster First Contentful Paint (FCP)

3. Direct Access to Server Resources

Server Components can:

  • Query a database

  • Fetch private APIs

  • Read files
    Without exposing secrets.

4. Great SEO

Content is generated on the server → search engines can index easily.

5. Modern Full-Stack Support

Perfect for frameworks like:

  • Next.js 13+

  • Remix (future updates)

  • RSC-ready systems

How to Migrate to React Server Components

Migration steps depend on your project setup. Below is the simplest path for modern React applications.

Step 1: Upgrade to Latest React and ReactDOM

Ensure you are using:

  • React 18 or above

  • ReactDOM 18 or above

Install the latest versions:

npm install react@latest react-dom@latest

Step 2: Use a Framework That Supports RSC

React Server Components work best in:

  • Next.js 13+ (App Router) — Recommended

  • Vite (with RSC plugins) — for custom setups

  • Remix (coming soon)

Best option: Next.js

Install Next.js 13+:

npx create-next-app@latest myapp

Select App Router, which is fully RSC-ready.

Step 3: Convert Your Components to Server or Client

Server Components (default)

All components are server components unless you add:

"use client";

When to use server components

  • Database calls

  • Heavy data fetching

  • Secure operations

  • Rendering large HTML lists

When to use client components

  • Event handlers (onClick, onChange)

  • Local state (useState)

  • useEffect

  • Animations

Step 4: Move Data Fetching to Server Components

Old React pattern:

useEffect(() => {
  fetch('/api/products').then(...);
}, []);

Modern RSC pattern:

export default async function Products() {
  const products = await fetch("https://api.example.com/products").then(r => r.json());
  return <ProductList items={products} />;
}

No useEffect needed.

Step 5: Split Client Logic Into Client Components

Example:

"use client";

export default function AddToCart({ id }) {
  return <button onClick={() => console.log("Added", id)}>Add to Cart</button>;
}

Use this inside a server component:

import AddToCart from "./AddToCart";

export default async function Product({ id }) {
  const product = await db.getProduct(id);
  return (
    <div>
      <h2>{product.name}</h2>
      <AddToCart id={product.id} />
    </div>
  );
}

Step 6: Use Layout and Streaming for Faster Loading

Next.js + RSC supports React Suspense and streaming.

Example:

export default function Layout({ children }) {
  return (
    <html>
      <body>{children}</body>
    </html>
  );
}

With Suspense:

<Suspense fallback={<p>Loading...</p>}>
  <Products />
</Suspense>

Step 7: Clean Up Old Client-Side Patterns

Remove unnecessary:

  • useEffect for data fetching

  • JSON parsing logic in browser

  • Client-side state management for server data

Replace with server functions and direct rendering.

Common Migration Issues and Fixes

1. Error: “useState is not allowed in Server Components”

Add:

"use client";

2. Private environment variables not accessible

Server Components CAN access .env, but client components cannot.

3. API routes returning unnecessary JSON

You can now call databases directly inside RSC — no need for API proxy.

Example Folder Structure in Next.js 13+

app/
  layout.js          // server component
  page.js            // server component
  products/
    page.js          // server
    ProductCard.js   // server
    AddToCart.js     // client

Best Practices for Migrating to RSC

  • Keep most components as server components.

  • Only use client components when necessary.

  • Offload heavy computation to server.

  • Use Suspense boundaries for streaming.

  • Avoid unnecessary client-side JavaScript.

  • Use server-side fetching instead of API calls.

Conclusion

React Server Components bring a major improvement to how React handles rendering, performance, and data fetching. By running components on the server and shipping less JavaScript to the client, you can build faster and more scalable applications. Migrating to RSC is straightforward once you upgrade to the latest React version and adopt best practices using modern frameworks like Next.js. With this new hybrid rendering model, React development becomes more powerful, secure, an