Course outline · 0% complete

0/29 lessons0%

Course overview →

Composing the two worlds

lesson 3-3 · ~11 min · 9/29

Mixing without dragging

Rules of composition:

  1. A server component can render a client component. This is the normal direction: the page (server) sprinkles in interactive leaves (client).
  2. A client component cannot import a server component. Importing pulls it into the client bundle, where server code cannot run.
  3. But a client component can receive server-rendered content as children. The classic props pattern from the React course is the escape hatch.

Pattern 3 is worth a picture in code:

// app/page.js  (server)
import Collapsible from "./collapsible"; // a "use client" wrapper
import HeavyArticle from "./article";    // stays a server component

export default function Page() {
  return (
    <Collapsible>
      <HeavyArticle />
    </Collapsible>
  );
}

Collapsible handles the open/close click in the browser, while HeavyArticle is rendered on the server and passed in as already-finished content.

Quiz

Why does the Collapsible pattern above keep HeavyArticle out of the browser bundle?

Quiz

A "use client" component adds import HeavyArticle from "./article" at the top of its file (article.js has no directive). What happens to HeavyArticle?

Choosing in practice

A quick decision list you can apply to any component:

  • Needs useState, useEffect, refs, event handlers, or browser APIs (localStorage, window)? → client.
  • Fetches data, reads env vars or a database, or just renders markup from props? → server (the default, do nothing).
  • Both? Split it: a server component for the data and markup, with a small client child for the interactive part.

This mirrors the frontend/backend split you already lived in the React and Backend with Node.js courses, except the boundary now runs through one component tree instead of between two repos.

Problem

A blog page tree has these components: PostBody (renders markdown from props), CommentForm (textarea with useState), AuthorCard (renders props), ThemeToggle (onClick + localStorage). How many of them need "use client"?