A mental model for Server vs Client Components

The rule of thumb I actually use when deciding whether a component needs 'use client', and how a Server Component parent can still pass data down to it.

2 min readUpdated April 18, 2026

Sabin Shrestha

Full-Stack Developer — Next.js, React & React Native

This is a running note — I add to it whenever I trip over the Server/Client boundary again, which is more often than I'd like to admit.

The rule of thumb #

Start every component as a Server Component

Only add "use client" when the file itself needs one of: useState/useEffect/other hooks, browser-only APIs (window, localStorage), event handlers (onClick etc.), or a third-party library that assumes a DOM (most animation libraries, most chart libraries).

Everything else — data fetching, anything touching the filesystem, anything that doesn't need interactivity — stays a Server Component by default.

The mistake I keep making #

Marking a component "use client" because it renders inside an interactive page, not because it itself needs interactivity. A component that just formats and displays a date doesn't need to be a Client Component just because its parent is one — Server Components can still be passed as children into Client Components.

Wrapper.tsx
"use client";
 
export default function Wrapper({ children }: { children: React.ReactNode }) {
  const [open, setOpen] = useState(false);
  return (
    <div>
      <button onClick={() => setOpen(!open)}>Toggle</button>
      {open && children /* ← can still be a Server Component */}
    </div>
  );
}

Passing server data into a client component #

The part that isn't obvious at first: a Client Component can't call a server-only function like fs.readFileSync itself, but it can receive the result of one as a prop from a Server Component parent. Same idea shows up in small hooks too — see the debounce hook snippet, which only needs "use client" because it uses useEffect, nothing more.

Open questions #

  • When does it actually pay off to split a "server fetch, client render" component into two files vs. just accepting one client boundary a little higher up the tree?
  • Worth measuring: how much smaller is the client bundle in practice when a heavy markdown-rendering step stays server-only?
© 2026 Sabin Shrestha