VOOZH about

URL: https://dev.to/0012303/react-server-components-have-a-free-data-fetching-model-no-more-useeffect-waterfalls-1jh2

⇱ React Server Components Have a Free Data Fetching Model — No More useEffect Waterfalls - DEV Community


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>
 );
}

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>
 );
}

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>
 );
}
// Client Component (opt-in with "use client")
"use client";
import { useState } from 'react';

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

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>
 );
}

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>
 );
}

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

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.