Under The Hood
frontend react React 19 (RSC stable in Next.js App Router)

React Server Components: the client/server boundary

Last updated
Prerequisites:
React component model
Next.js App Router basics
  • react
  • server-components
  • nextjs
  • serialization
  • rsc
  • architecture

Read at your depth

The practical view

In Next.js App Router, components are Server Components by default: export default async function Page() { const data = await fetch(...); return <List items={data} />; } runs entirely on the server — the async/await, the fetch, the file system access — and ships only rendered output. Files with 'use client' at the top become Client Components: their JS bundle ships to the browser and they can use useState, useEffect, and event handlers. The boundary rule: a Client Component can be rendered inside a Server Component, but props crossing the boundary must be serializable (no functions, no class instances, no Date unless wrapped in a serializable form).

The same idea in other frameworks

react equivalent
// page.jsx (Server Component, no 'use client')
export default async function Page() {
  const posts = await db.query('SELECT * FROM posts');
  return <PostList posts={posts} />;
}

Legacy vs modern

Fetching data in the client component vs in a server component

Client-side fetching ships the fetch logic, the endpoint URL, and double-loads state; a server component fetches once, server-side, and passes serializable props down.

before → after
Client component fetch
'use client';
const [posts, setPosts] = useState([]);
useEffect(() => { fetch('/api/posts').then(r => r.json()).then(setPosts); }, []);
Server component fetch
export default async function Posts() {
  const posts = await db.query('SELECT * FROM posts');
  return posts.map((p) => <li key={p.id}>{p.title}</li>);
}

Interview gotchas

Under The Hood — a multi-depth technical interview hub.

Press ⌘ K to search.