// BLOG_ENTRYFEATURED

React Server Components in Practice

When to reach for Server Components, when to keep Client Components, and how to draw the boundary without turning your app into a guessing game.

REACTNEXT.JSARCHITECTURE
PUBLISHED
Mar 12, 2026
READ_TIME
8 min
TOPIC
React · Server Components
AUTHOR
Eltaj Mammadzada
SEC_01
INTRO

The Boundary Problem

Server Components aren't a replacement for React — they're a layer in the stack. The mistake I see most often isn't using them too little. It's using them without a rule for where client interactivity actually lives.

In production apps, that boundary shows up everywhere: dashboards with filters, forms with validation, widgets that respond to scroll. The goal isn't zero client JavaScript. It's putting JavaScript only where the user needs it.

Server Components reduce bundle size. Clear boundaries reduce mental load.

SEC_02
PATTERN

A Simple Decision Tree

Start with the page as a Server Component. Fetch data on the server. Render static structure and content that doesn't need browser APIs.

Extract a Client Component only when you need useState, useEffect, event handlers, or browser-only APIs. Pass serializable props down — never pass functions from server to client unless they're Server Actions.

Keep client islands small. A filter bar can be client; the data table body can stay server-rendered with the filtered result passed as props from a parent that re-fetches or uses searchParams.

app/dashboard/page.tsx
// Server Component — data fetch at the edge
export default async function DashboardPage() {
  const stats = await getStats();
  return (
    <main>
      <StatsGrid data={stats} />
      <FilterBar /> {/* client island */}
    </main>
  );
}
SEC_03
OUTRO

What Actually Stuck

After shipping several Next.js App Router projects, the teams that moved fastest had a written rule: default server, justify client. Not the other way around.

Document the boundary in your README or ADR. Future you — and the next developer — will thank you when the app is 40 routes deep and still predictable.

  • Default to Server Components for pages and data-heavy layouts.
  • Client Components for interactivity — keep them leaf nodes when possible.
  • Co-locate fetching with the component that owns the data contract.