Home About Services Work Blog Contact
connect@ajinthan.com · Colombo, Sri Lanka
Web Development

React Server Components: When to Reach for the Client

A mental model for the server/client boundary in the Next.js App Router — what runs where, why it matters, and how to ship less JavaScript.

React Server Components: When to Reach for the Client

The biggest shift in the Next.js App Router isn't the file structure — it's that components are server components by default. Get the mental model right and you ship faster sites with less code. Get it wrong and you fight the framework all day.

The default is the server

Every component is a server component unless you opt out. Server components:

  • Run only at build or request time — their code never reaches the browser.
  • Can be async and fetch data directly.
  • Can't use hooks, state, effects, or browser APIs.

That last point isn't a limitation; it's the whole benefit. Code that doesn't need the browser doesn't get sent to it.

"use client" marks a boundary, not a file

The directive doesn't just make one component interactive — it marks the start of a client subtree. Everything imported into a client component travels to the browser too. So push the directive as far down the tree as you can.

// page.tsx — server component, no JS shipped
export default async function Page() {
  const posts = await getPosts();
  return (
    <>
      <PostList posts={posts} />   {/* server */}
      <SearchBox />                {/* client island */}
    </>
  );
}

A small interactive island in a sea of static, server-rendered content — that's the shape you're aiming for.

Pass data down, not functions

Server components can render client components and pass them serializable props — strings, numbers, plain objects. They can't pass functions. So shape your data on the server and hand the client component exactly what it needs to render:

<WorkFilters items={projects} />   // data in, interactivity inside

A simple decision rule

Ask one question of each component: does this need the browser?

  • No — leave it as a server component. Most of your UI lands here.
  • Yes — it uses state, effects, event handlers, or browser APIs? Mark it "use client", and keep it small.

Think of client components as islands of interactivity, not the continent. The continent should be server-rendered HTML.

This model is why an App Router site can feel instant: the browser gets meaningful HTML immediately and only hydrates the few pieces that actually need to be interactive. Less JavaScript, faster pages, better Core Web Vitals — all from respecting one boundary.

Next.jsReactServer ComponentsPerformance
AT
Ajinthan Thavendrarajah

Based in Colombo, Sri Lanka, building scalable web & mobile products with .NET, NestJS, Next.js and Flutter.

Keep reading

Related articles.