'use client' at the leaves
Mark only interactive leaves; fetch in an async server parent.
React docsreact.dev
Reference for the 'use client' directive: marks a component as a Client Component.
From next-best-practices, rsc-boundaries.md and directives.md.
Where the boundary goes
Click a node to toggle 'use client', or pick a preset.
app/shop/page.tsx treeTree
Result—
JS shipped
// app/shop/page.tsx
export default async function Page() {
const products = await db.product.findMany()
return <ProductList products={products} />
}
// add-to-cart-button.tsx
'use client'
import { useState } from 'react'
export function AddToCartButton({ id }: { id: string }) {
const [pending, setPending] = useState(false)
return <button onClick={() => addToCart(id)}>Add</button>
}
Async client component linter
Edit or toggle, then press Split it to fix.
—
Linterrsc-boundaries
page.tsx
// not created yet
// page.tsx
export default async function Page() {
const user = await getUser()
return <UserProfile user={user} />
}
// user-profile.tsx
'use client'
export function UserProfile({ user }: { user: User }) {
return <div>{user.name}</div>
}
Server, Client, or split?
Tick what one component needs.
ComponentUses
Verdict—
Why it matters, pros and cons
Why it matters
'use client' ships the file and its imports. Only Server Components can await.
Pros
- Less JS in the browser.
- Secrets and DB clients stay server-side.
- Interactive parts stay small and findable.
Cons
- Props across the boundary must be serializable.
- Very interactive screens are client at the top anyway.
- Server children pass only as
children, not imports.