У App Router компоненти за замовчуванням серверні. Директива 'use client' на початку файлу позначає межу: цей модуль і все, що він імпортує, потрапляє в клієнтський бандл.
// app/products/[id]/page.tsx - серверний компонент
import AddToCart from './add-to-cart';
export default async function Page({ params }) {
const { id } = await params;
const product = await db.product.find(id); // запит прямо в компоненті
return (
<>
<h1>{product.name}</h1>
<AddToCart productId={product.id} price={product.price} />
</>
);
}
// add-to-cart.tsx
'use client';
export default function AddToCart({ productId, price }) {
const [qty, setQty] = useState(1);
return <button onClick={() => addToCart(productId, qty)}>У кошик - {price * qty} грн</button>;
}
Що можна передати з серверного в клієнтський компонент - лише серіалізовані значення:
- примітиви, звичайні об'єкти й масиви,
Date,Map,Set, типізовані масиви; - Promise (клієнт розгорне через
use()); - React-елементи (JSX), зокрема
children; - серверні функції (
'use server').
Не можна: звичайні функції (обробники подій), екземпляри класів, моделі ORM з методами, символи (крім глобально зареєстрованих).
Важливі наслідки:
- усе передане видно в браузері. Передати в клієнтський компонент повний об'єкт користувача з бази - відправити в HTML і хеш пароля, і службові поля. Передавайте лише потрібні поля;
- межу ставлять якомога нижче - на інтерактивний «листок» (кнопка, форма), а не на всю сторінку. Інакше весь вміст і його залежності йдуть у бандл;
- серверний компонент можна вставити в клієнтський через
children, але не імпортувати в клієнтський модуль напряму - імпорт перетворить його на клієнтський; - контекст і провайдери (
ThemeProvider) - клієнтські компоненти, що обгортаютьchildrenу макеті; - бібліотеки без
'use client', що використовують хуки, треба обгорнути у власний клієнтський модуль.
'use client' - не «рендер лише в браузері». Клієнтські компоненти теж рендеряться на сервері при першому завантаженні (SSR), а потім гідруються. Тому в їхньому рендері не можна звертатися до window без перевірок.
Докладніше в документації: Next.js: серверні й клієнтські компоненти