ESC

Type to search the knowledge base.

Server Components Overview

React Server Components run on the server: zero client JS for their logic, async data, and composition with client leaves.

advanced3 min read
  • react
  • server-components

Server Components (RSC) render on the server into a special payload the client hydrates selectively. They can be async, read databases and secrets (with care), and do not ship their own component logic as client JS. Interactive islands opt into Client Components.

Docs: Server Components, Next.js.

What you gain

Benefit Why
Smaller bundles Server-only code never goes to the client
Direct data access await db.query in the component
Secure by default Secrets stay server-side
Streaming Frameworks can stream UI as data resolves

What you cannot do on the server

  • useState, useEffect, browser DOM APIs
  • Event handlers like onClick on the server component itself
  • Importing client-only libraries without a client boundary

Composition

// Server
async function Notes() {
  const notes = await getNotes();
  return (
    <ul>
      {notes.map((n) => (
        <li key={n.id}>
          {n.title}
          <EditButton noteId={n.id} /> {/* client */}
        </li>
      ))}
    </ul>
  );
}

Keep client boundaries at interactive leaves.

Mental model versus classic SSR

Classic SSR still sent a full client React tree to hydrate. RSC can keep large pure UI server-only. Hydration applies mainly to client islands. Mismatches still matter for those islands (hydration).

Interview out-loud

“Server Components render on the server, can be async, and avoid shipping their logic to the client. I fetch data on the server, pass serializable props to client children, and use composition so client shells wrap server content via children. Hooks and browser APIs require Client Components.”

Further reading

Edge cases worth rehearsing

Interviewers and production incidents cluster around the same edges: first render versus update, empty and loading states, Strict Mode double setup, concurrent interruptions, and what happens when identity (key, route params, user id) changes mid-edit. Walk one concrete user journey end-to-end — open, edit, navigate away, come back — and say which state survives.

Prefer fixing data flow and ownership before reaching for memoization or micro-optimizations. Prefer event handlers over effects when a user action is the trigger. Prefer deriving values during render over mirroring props into state. Prefer stable list keys from business ids. Measure with the profiler when performance is the claim.

When you cite an API, mention one failure mode: abort on unmount, serializable props across server/client boundaries, focus restoration for dialogs, or cache invalidation after a mutation. Specific beats generic every time.

Edge cases worth rehearsing

Interviewers and production incidents cluster around the same edges: first render versus update, empty and loading states, Strict Mode double setup, concurrent interruptions, and what happens when identity (key, route params, user id) changes mid-edit. Walk one concrete user journey end-to-end — open, edit, navigate away, come back — and say which state survives.

Prefer fixing data flow and ownership before reaching for memoization or micro-optimizations. Prefer event handlers over effects when a user action is the trigger. Prefer deriving values during render over mirroring props into state. Prefer stable list keys from business ids. Measure with the profiler when performance is the claim.

When you cite an API, mention one failure mode: abort on unmount, serializable props across server/client boundaries, focus restoration for dialogs, or cache invalidation after a mutation. Specific beats generic every time.

Related guides