tanjilahmed87@gmail.com

Frontend6 min read

The Mental Model That Finally Made React Server Components Click

Forget 'server' and 'client' as a spectrum. The model that actually clicked was thinking in terms of what crosses the network boundary.

Tanjil Ahmed

Lead Software Engineer · Notionhive

React Server Components confused me for longer than I'd like to admit, because I kept thinking of 'server' and 'client' as two flavors of the same component model. The mental shift that made it click was different: stop thinking about where code runs, and start thinking about what data crosses the network as serialized props.

The boundary is a serialization boundary, not a rendering boundary

A Server Component can pass a plain object, a string, a number — anything JSON-serializable — down to a Client Component as props. It cannot pass a function, a class instance, or a Date object without care. Once I started asking 'can this cross a serialization boundary?' instead of 'does this need interactivity?', the placement of the `"use client"` directive stopped being a guessing game.

  • Push `"use client"` as low in the tree as possible — it's contagious downward, not upward.
  • Server Components can be async and fetch data directly; that's a feature, not a workaround.
  • Context providers need a client boundary — they can't live purely on the server.
  • Composition beats prop drilling: pass Server Component children into Client Component slots to keep more of the tree server-rendered.
RSC isn't a new rendering mode to learn. It's the same React, with a new question: what has to cross the wire?