iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

SSR & React Server Components

React Server Components (RSC) are the biggest architectural shift in React in years - the server renders components into a streamable format that the client can hydrate selectively.

RSC fundamentals

EXAMPLE
// 1. The mental model
// - Server components run on the server, can fetch data, but cannot use state/effects or browser APIs.
// - Client components run on the client (and during SSR), can use state/effects.
// - You compose: server components import client components freely; the reverse only via props that are serialisable.

// 2. Server component - default in app/ in Next 13+
// app/users/page.tsx
import { db } from '@/lib/db';
import { UserListClient } from './UserListClient';

export default async function UsersPage() {
  const users = await db.users.findMany();
  return <UserListClient users={users} />;
}

// 3. Client component - opt-in with directive
// app/users/UserListClient.tsx
'use client';
import { useState } from 'react';

type Props = { users: { id: string; name: string }[] };

export function UserListClient({ users }: Props) {
  const [q, setQ] = useState('');
  return (
    <div>
      <input value={q} onChange={(e) => setQ(e.target.value)} />
      <ul>
        {users.filter((u) => u.name.includes(q)).map((u) => (
          <li key={u.id}>{u.name}</li>
        ))}
      </ul>
    </div>
  );
}

// 4. Server actions - call server code from client components
// app/actions.ts
'use server';
export async function createUser(formData: FormData) {
  await db.users.create({ name: String(formData.get('name')) });
}

// app/users/Add.tsx
'use client';
import { createUser } from '../actions';

export function Add() {
  return (
    <form action={createUser}>
      <input name='name' />
      <button>Add</button>
    </form>
  );
}

// 5. Streaming with Suspense
import { Suspense } from 'react';

export default function Dashboard() {
  return (
    <div>
      <h1>Stats</h1>
      <Suspense fallback={<p>loading...</p>}>
        <Stats />     {/* server component fetching data */}
      </Suspense>
    </div>
  );
}

// 6. Things you cannot do in a server component
// - useState, useEffect, useRef
// - Browser APIs (window, document)
// - Event handlers in returned JSX (onClick on a button must be in a client component)

// 7. Things RSC unlocks
// - Big DB queries directly in the component, no API layer
// - Smaller JS bundle - client components are only the interactive bits
// - Streaming UI - render shell first, suspense the slow bits

// 8. State of the union (2026)
// - Next.js App Router: production-ready RSC
// - React Router v7 framework mode: server components opt-in
// - Most other frameworks: not yet, or experimental

Why it matters

RSC moves the data layer out of useEffect and into the component itself. The bundle shrinks; the queries co-locate with the JSX. Client components keep doing what they always did. Start with everything as a server component; opt into client only where you actually need state.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// React Server Components run only on the server — no client JS shipped.
async function Posts() { const data = await db.posts.findMany(); return <List items={data} />; }
Try it Yourself »

Discussion

Loading…