C.W.K.
Stream
Lesson 03 of 08 · published

Client Components

~20 min · use client, interactivity, hooks

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

When you need the browser

State, events, refs, browser APIs, third-party UI libraries (Framer Motion, headless UI, React Hook Form). For these, declare the file a Client Component with 'use client' at the very top.

The directive is contagious

'use client' applies to the file and everything it imports. Anything in the import graph below the directive is part of the client bundle. Place it as low in the tree as possible.

The decision table

NeedWhere
useState / useEffect / useRefClient
Event handlers (onClick, onChange, onSubmit)Client
window, document, localStorageClient
Third-party hook-based librariesClient
Plain rendering of dataServer
Data fetching / DB queriesServer
Reading secretsServer
Heavy data shapingServer

Code

Smallest possible Client Component·tsx
'use client';
import { useState } from 'react';

export function Counter({ initial = 0 }: { initial?: number }) {
  const [count, setCount] = useState(initial);
  return (
    <button
      onClick={() => setCount(c => c + 1)}
      className="rounded bg-blue-600 px-3 py-1 text-white"
    >
      {count}
    </button>
  );
}
Server parent renders client leaf·tsx
// app/page.tsx — Server Component
import { Counter } from '@/components/Counter';

export default async function Page() {
  const initial = await fetch('https://api.example.com/count').then(r => r.json());
  return <Counter initial={initial.value} />;
}

External links

Exercise

Find a Client Component in your app that wraps a server-renderable subtree. Push 'use client' down to the smallest leaf that actually needs interactivity, and confirm the surrounding nodes drop out of the client bundle.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.