Concepts

Published 2026-06-01Updated 2026-07-16

use client

Declaring the Client Component boundary

Clarifying Concepts

CSR

Client-Side Rendering.

Core definition: the main content of a page is rendered by JavaScript executed in the browser. Data sources can be:

  • fetch;
  • data hardcoded in JS;
  • other similar approaches;

CSR = the main UI content of HTML depends on browser JS execution to be produced.

bundle

Original meaning: a bundle, a bale, a package of things. In frontend engineering, it can be understood as: a group of JavaScript code/resources packaged for the browser after being processed by a build tool.

For example:

TypeScript
import React from 'react'
import Button from './Button'
import { formatDate } from './utils'

These pieces of code are scattered across:

Markdown
page.tsx
Button.tsx
utils.ts
React
third-party dependencies
...

The build tool analyzes the dependency relationships between these modules:

Markdown
source code modules
   ↓
dependency graph
   ↓
compile / transform / optimize / split
   ↓
one or more JS files

The code ultimately delivered to the browser is typically referred to as: JavaScript bundle, client bundle, bundle size, etc.

Next.js doesn't crudely stuff everything into a single bundle.js; in practice, it performs code splitting/chunking, producing multiple chunks.

Therefore, bundle can be understood as: the packaged collection of client-side code.

prerender

Markdown
pre + render
beforehand + render

Rendering the page ahead of time, before the user actually visits it. This is a general concept in Web / SSR / SSG.

Hydration

hydrate itself means: to supply water to something.

Imagine the HTML obtained from build as a: dry page that already has: tags, text, structure, content, but lacks React client-side behavior.

After the browser loads JS, React performs hydration on the existing HTML: rather than tearing down and rebuilding the page, it injects/restores client-side capabilities on top of the existing HTML.

During hydration, the result of the client's first render does need to match the HTML obtained from server-side/pre-rendering.

Therefore, translated as: hydration, it is the core mechanism in React's SSR/pre-rendering system. React takes over the existing HTML in the browser and turns it into an interactive React application.

Plain text
Existing HTML

<button>0</button>
      β”‚
      β”‚ Download Client JS
      ↓
React executes
      β”‚
      ↓
Hydration
      β”‚
      β”œβ”€β”€ Build React component tree
      β”œβ”€β”€ Map React to existing DOM
      β”œβ”€β”€ Set up event handlers
      └── Restore interactivity
             ↓
        button is clickable

Understanding

The most straightforward understanding: declaring a Client Component boundary.

  • This is distinct from "Client Component" and "CSR pure client-side rendering" β€” they are not the same thing.
  • It indicates that this component needs client-side JavaScript capabilities; it does NOT mean this component can only generate HTML on the client.

How to understand this?

With static export, Client Components are also pre-rendered during the next build phase; static HTML for the initial visit is still produced.

TypeScript
'use client'
 
import { useState } from 'react'
 
export default function Counter() {
  const [count, setCount] = useState(0)
 
  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  )
}

Here, 'use client' essentially tells Next.js: starting from this file, establish a Server / Client boundary; this module and its client dependencies need to be included in the browser JavaScript bundle.

  • Next.js page.tsx and layout.tsx are Server Components by default. You should only establish a 'use client' boundary when you need client-side capabilities.

For example:

Markdown
page.tsx                Server Component
β”‚
β”œβ”€β”€ Article.tsx         Server Component
β”‚
└── LikeButton.tsx      Client Component
      ↑
      'use client'

The general flow is as follows:

Markdown
next build
   β”‚
   β”œβ”€β”€ Server Components execute
   β”‚
   β”œβ”€β”€ Client Components also participate in pre-rendering
   β”‚
   ↓
Generate static HTML
   +
Generate JS for Client Components
   ↓
Browser
   β”‚
   β”œβ”€β”€ Display HTML first
   └── JS hydration
          ↓
       onClick / state / effect take effect

You need a Client Component in the following cases:

  • useState
  • useEffect
  • event handlers, e.g. onClick, onChange
  • browser APIs, e.g. window, document, localStorage, Geolocation
  • custom hooks that depend on these capabilities

Any UI that depends on browser runtime state, lifecycle, events, or Browser APIs generally needs to be inside a Client Component boundary.

TypeScript
'use client'
 
function Counter() {
  const [count, setCount] = useState(0)
 
  useEffect(() => {
    console.log('browser')
  }, [])
 
  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  )
}

Broken down:

Markdown
BUILD
────────────────
 
Counter render
    ↓
<button>0</button>
    ↓
Write to HTML
 
 
BROWSER
────────────────
 
HTML displayed immediately
    ↓
Download Counter JS
    ↓
React hydration
    ↓
useEffect executes
    ↓
onClick starts working
    ↓
useState can change

SEO, first-screen content, and performance are not determined by use client, but by: whether the core content is already in the HTML at build time.

TypeScript
'use client'
 
function Article() {
  return (
    <article>
      <h1>TypeScript Basics</h1>
      <p>This is an article…</p>
    </article>
  )
}

This will still be pre-rendered into HTML. The HTML that search engines receive may itself contain:

HTML
<h1>TypeScript Basics</h1>
<p>This is an article…</p>

What you need to watch out for is code like this:

TypeScript
'use client'
 
function Article() {
  const [content, setContent] = useState('')
 
  useEffect(() => {
    fetch('/article.json')
      .then(...)
      .then(setContent)
  }, [])
 
  return <article>{content}</article>
}

At build time, this may only produce:

HTML
<article></article>

After the browser executes JS, it becomes:

HTML
<article>
  Lots of content…
</article>
Markdown
            Next.js App Router
 
                    Component
                        β”‚
            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
            β”‚                       β”‚
    Server Component        Client Component
        default                  'use client'
            β”‚                       β”‚
    build/server execution      needs browser JS
            β”‚                       β”‚
            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                    prerender
                        β”‚
                    HTML
                        β”‚
                    Browser loads
                        β”‚
                Client JS hydration
                        β”‚
                    Interactive