Skip to content
</>CodeAndBuild

React

A mental model for React Server Components

Server Components render on the server, Client Components cross a serializable boundary, and the file directive is what marks that line.

8 min read
  • React
  • Server Components
  • Next.js
On this page
  1. The boundary is the file, not the function
  2. Props must survive serialization
  3. Compose children from the server

In the App Router, a component is a Server Component unless its file starts with "use client". The directive opts that file, and every module it imports, into the client bundle. It does not mean the component runs only in the browser. Client Components still pre-render on the server, and then they hydrate.

The boundary is the file, not the function

Put the directive in the leaf that needs state, effects, or a browser API. A button that tracks a copied flag does not force the whole page into the client bundle, as long as the page passes plain props into that button.

components/CopyButton.tsxtsx
"use client";

import { useState } from "react";

export function CopyButton({ value }: { value: string }) {
  const [copied, setCopied] = useState(false);

  return (
    <button
      type="button"
      onClick={async () => {
        await navigator.clipboard.writeText(value);
        setCopied(true);
      }}
    >
      {copied ? "Copied" : "Copy"}
    </button>
  );
}

Props must survive serialization

Values passed from a Server Component to a Client Component are serialized. Strings, numbers, plain objects, and arrays travel. Functions, class instances, and Date objects do not. Format the date on the server and pass a string.

  • Keep data fetching in Server Components.
  • Keep event handlers in Client Components.
  • Pass ids and already formatted strings across the boundary.

Compose children from the server

When an interactive shell needs server-rendered content, pass that content as children. The shell can be a Client Component while the child stays a Server Component, because the child was created in a server file and handed in.

  1. 01

    Build the interactive shell

    Keep the client file small: state, events, and the markup that depends on them.

  2. 02

    Render it from a server file

    The server file fetches data and passes server content as children.

  3. 03

    Do not refetch to avoid composition

    A second fetch inside the shell usually means the boundary was drawn around too much UI.

More guides

SEO6 min

Technical SEO for a developer blog

Write a specific title, give each guide one URL, and make the heading structure match the outline a reader would sketch.