Chapter 1 · Practice 1 of 5
Keep components on the server and add use client only at the leaves
Why it matters
Where a component runs decides how much JavaScript you ship and what it can safely touch. In the App Router every component is a Server Component unless its file starts with 'use client'.
- Server Components can read databases and secrets directly and ship no JavaScript to the browser.
'use client'marks a boundary: that file and everything it imports become part of the client bundle.
Put the directive as low in the tree as you can, on the small interactive pieces such as a like button, a search box or a menu. Keep pages and layouts as Server Components and pass server-rendered content into client components through children.
tsx
// like-button.tsx
'use client';
import { useState } from 'react';
export function LikeButton({ postId }: { postId: string }) {
const [liked, setLiked] = useState(false);
return <button onClick={() => setLiked(!liked)}>Like</button>;
}
Do
- Add
use clientto the smallest component that needs state, effects or browser APIs - Pass Server Components into Client Components as
children
Avoid
- Marking a whole page or layout as a Client Component to use one hook
Example
// app/post/[slug]/page.tsx (Server Component)
import { LikeButton } from './like-button';
export default async function Page({ params }: PageProps<'/post/[slug]'>) {
const { slug } = await params;
const post = await getPost(slug);
return (
<article>
<h1>{post.title}</h1>
<LikeButton postId={post.id} />
</article>
);
}