DEV Community

Alex Spinov
Alex Spinov

Posted on

React Server Components Have a Free Data Fetching Model — No More useEffect Waterfalls

useEffectfetch → loading spinner → another useEffect → another fetch → another spinner. React Server Components end this waterfall permanently.

What Are React Server Components?

RSCs run exclusively on the server. They can directly access databases, file systems, and APIs — then send the rendered HTML to the client. No loading spinners. No client-side fetch calls.

Why RSCs Change Everything

1. Direct Database Access in Components

// This component runs on the server — never ships to the browser
async function UserProfile({ userId }: { userId: string }) {
  const user = await db.users.findUnique({ where: { id: userId } });
  const posts = await db.posts.findMany({ where: { authorId: userId } });

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.bio}</p>
      <PostList posts={posts} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

No API route. No useEffect. No loading state. The HTML arrives ready.

2. Zero Client-Side JavaScript

// Server Component — 0 KB shipped to browser
async function ProductCatalog() {
  const products = await db.products.findMany({
    where: { active: true },
    orderBy: { createdAt: 'desc' },
  });

  return (
    <div className="grid grid-cols-3 gap-4">
      {products.map(p => (
        <div key={p.id}>
          <img src={p.imageUrl} alt={p.name} />
          <h3>{p.name}</h3>
          <p>${p.price}</p>
        </div>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This component could render 10,000 products and ship 0 bytes of JavaScript.

3. Mix Server and Client Components

// Server Component (default in Next.js App Router)
async function Dashboard() {
  const stats = await getStats();  // Server-side data fetch

  return (
    <div>
      <h1>Dashboard</h1>
      <StatsDisplay stats={stats} />          {/* Server — no JS */}
      <InteractiveChart data={stats.chart} />  {/* Client — has JS */}
      <RecentActivity items={stats.recent} />  {/* Server — no JS */}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode
// Client Component (opt-in with "use client")
"use client";
import { useState } from 'react';

function InteractiveChart({ data }) {
  const [timeRange, setTimeRange] = useState('7d');
  // ... interactive chart logic
}
Enter fullscreen mode Exit fullscreen mode

4. Streaming and Suspense

async function Page() {
  return (
    <div>
      <Header />  {/* Renders immediately */}

      <Suspense fallback={<Skeleton />}>
        <SlowDataSection />  {/* Streams in when ready */}
      </Suspense>

      <Suspense fallback={<Skeleton />}>
        <AnotherSlowSection />  {/* Streams in independently */}
      </Suspense>

      <Footer />  {/* Renders immediately */}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

5. Server Actions (Mutations)

async function CreatePost() {
  async function createPost(formData: FormData) {
    "use server";
    const title = formData.get('title') as string;
    const content = formData.get('content') as string;
    await db.posts.create({ data: { title, content } });
    revalidatePath('/posts');
    redirect('/posts');
  }

  return (
    <form action={createPost}>
      <input name="title" required />
      <textarea name="content" required />
      <button type="submit">Publish</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

RSC vs Traditional React

Server Components Client Components
Runs on Server only Browser
JS shipped 0 KB Full component code
Data access Direct DB/fs/API Via fetch/API
Interactivity None (static HTML) Full (state, events)
Use for Data display, layout Forms, charts, modals

Getting Started

RSCs are built into Next.js App Router (13.4+):

npx create-next-app@latest --app
# All components are Server Components by default
# Add "use client" only when you need interactivity
Enter fullscreen mode Exit fullscreen mode

The Bottom Line

Server Components eliminate the client-server waterfall. Fetch data where it lives (the server), render HTML, send it to the browser. Less JavaScript, faster pages, simpler code.


Need data tools? I build scraping solutions. Check my Apify actors or email spinov001@gmail.com.

Top comments (0)