Компоненти сервера React (rsc)
Що таке React Server Components?
React Server Components (RSC) — це компоненти, які виконуються тільки на сервері. Вони ніколи не виконуються в браузері, ніколи не відправляють JavaScript клієнту і можуть безпосередньо отримувати доступ до серверних ресурсів (бази даних, файлової системи, API).
Серверні vs Клієнтські компоненти
// Серверний компонент (за замовчуванням у Next.js App Router)
// ✅ Немає директиви "use client" — виконується на сервері
async function UserProfile({ userId }: { userId: string }) {
// Прямий доступ до бази даних — API не потрібен!
const user = await db.query.users.findFirst({
where: eq(users.id, userId)
});
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
<LikeButton userId={userId} /> {/* Клієнтський компонент */}
</div>
);
}// Клієнтський компонент — потрібна директива "use client"
"use client";
import { useState } from "react";
function LikeButton({ userId }: { userId: string }) {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked(!liked)}>
{liked ? "❤️ Лайкнуто" : "🤍 Лайк"}
</button>
);
}Основні відмінності
| Особливість | Серверний компонент | Клієнтський компонент |
|---|---|---|
Директива "use client" | Ні | Так |
| Виконується на | Тільки сервері | Сервер (SSR) + Клієнт |
| Розмір JS бандла | Нуль (не надсилається клієнту) | Включено в JS бандл |
useState, useEffect | ❌ Не можна використовувати | ✅ Можна використовувати |
| Обробники подій (onClick) | ❌ Не можна використовувати | ✅ Можна використовувати |
| Асинхронний компонент | ✅ Може бути асинхронним | ❌ Не може бути асинхронним |
| Доступ до БД/файлової системи | ✅ Безпосередньо | ❌ Тільки через API |
| Доступ до браузерних API | ❌ Немає доступу до window/document | ✅ Повний доступ |
Правила композиції
Серверний компонент → може рендерити серверні або клієнтські компоненти ✅
Клієнтський компонент → може рендерити ТІЛЬКИ клієнтські компоненти ❌
Клієнтський компонент → може приймати серверний компонент як дочірній (через props) ✅// ✅ Передача серверного компонента як дочірнього до клієнтського компонента
// layout.tsx (серверний компонент)
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<ClientSidebar>
{children} {/* дочірні компоненти можуть бути серверними компонентами */}
</ClientSidebar>
);
}Переваги
1. Нульовий розмір бандла
Серверні компоненти не додають JavaScript до бандла клієнта. Важкі бібліотеки, які використовуються тільки для рендерингу (наприклад, підсвічування синтаксису, парсинг markdown), залишаються на сервері:
// Серверний компонент — бібліотека marked залишається на сервері
import { marked } from "marked"; // НЕ надсилається клієнту
import hljs from "highlight.js"; // НЕ надсилається клієнту
async function BlogPost({ slug }: { slug: string }) {
const post = await getPost(slug);
const html = marked(post.content); // Оброблено на сервері
return <article dangerouslySetInnerHTML={{ __html: html }} />;
}2. Прямий доступ до даних
// Не потрібні API маршрути — запит безпосередньо
async function ProductList() {
const products = await db.select().from(productsTable);
return (
<ul>
{products.map(p => (
<li key={p.id}>{p.name} — ${p.price}</li>
))}
</ul>
);
}3. Потокове передавання та Suspense
import { Suspense } from "react";
export default function Page() {
return (
<div>
<h1>Панель управління</h1>
<Suspense fallback={<Skeleton />}>
<SlowDataComponent /> {/* Потокове передавання, коли готово */}
</Suspense>
</div>
);
}Коли використовувати що
| Використовуйте серверний компонент, коли | Використовуйте клієнтський компонент, коли |
|---|---|
| Отримання даних | Використання стану (useState) |
| Доступ до ресурсів бекенду | Використання ефектів (useEffect) |
| Зберігання чутливих даних на сервері | Використання обробників подій (onClick) |
| Зменшення JS бандла клієнта | Використання браузерних API |
| Важкі залежності (markdown тощо) | Використання кастомних хуків зі станом |
Важливо:
React Server Components кардинально змінюють спосіб, яким ми створюємо React додатки. Серверні компоненти виконуються тільки на сервері, мають нульову вартість JS для клієнта і можуть безпосередньо отримувати доступ до ресурсів бекенду. Використовуйте їх для отримання даних і рендерингу; використовуйте клієнтські компоненти тільки тоді, коли вам потрібна інтерактивність (стан, події, браузерні API). Вони є за замовчуванням у Next.js App Router.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.