Назад к блогу
Разработка

React Server Components: Полное руководство

Разбираемся в новой архитектуре React: что такое Server Components, как они работают и когда их использовать.

5 января 2026 г.
10 мин чтения
63 просмотров
MOLOTILO

MOLOTILO DIGITAL

React Server Components: Полное руководство

Что такое React Server Components?

React Server Components (RSC) — это новая архитектура React, позволяющая рендерить компоненты на сервере без отправки их JavaScript-кода клиенту. Это революционный подход, который меняет способ построения React-приложений.

Ключевые преимущества

  • Меньший размер бандла — серверный код не попадает к клиенту
  • Прямой доступ к данным — можно обращаться к БД напрямую
  • Улучшенный SEO — контент рендерится на сервере
  • Быстрая начальная загрузка — меньше JavaScript для парсинга

Server vs Client Components

// ✅ Server Component (по умолчанию в Next.js App Router)
import { db } from '@/lib/database';

async function ProductList() {
  // Прямой доступ к базе данных!
  const products = await db.product.findMany({
    where: { isActive: true },
    include: { category: true }
  });

  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>
          {product.name} - {product.price}₽
        </li>
      ))}
    </ul>
  );
}

// ❌ Client Component — нужна директива 'use client'
'use client';

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Clicked {count} times
    </button>
  );
}

Когда использовать Client Components

// Нужен 'use client' для:

// 1. Интерактивность
'use client';
function LikeButton() {
  const [liked, setLiked] = useState(false);
  return <button onClick={() => setLiked(!liked)}>❤️</button>;
}

// 2. Браузерные API
'use client';
function WindowSize() {
  const [size, setSize] = useState({ width: 0, height: 0 });
  
  useEffect(() => {
    const handleResize = () => {
      setSize({ width: window.innerWidth, height: window.innerHeight });
    };
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  
  return <div>{size.width} x {size.height}</div>;
}

// 3. Хуки React (useState, useEffect, useContext)
'use client';
function ThemeToggle() {
  const { theme, setTheme } = useContext(ThemeContext);
  return <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>Toggle</button>;
}

Паттерн композиции

// app/products/[id]/page.tsx (Server Component)
import { db } from '@/lib/database';
import { AddToCartButton } from '@/components/AddToCartButton';

export default async function ProductPage({ params }: { params: { id: string } }) {
  const product = await db.product.findUnique({
    where: { id: params.id },
    include: { images: true }
  });

  if (!product) return notFound();

  return (
    <div className="grid grid-cols-2 gap-8">
      <ProductGallery images={product.images} />
      
      <div>
        <h1>{product.name}</h1>
        <p>{product.description}</p>
        <p className="text-2xl font-bold">{product.price}₽</p>
        
        <AddToCartButton productId={product.id} />
      </div>
    </div>
  );
}

// components/AddToCartButton.tsx
'use client';

import { useState } from 'react';

export function AddToCartButton({ productId }: { productId: string }) {
  const [pending, setPending] = useState(false);

  const handleClick = async () => {
    setPending(true);
    await addToCart(productId);
    setPending(false);
  };

  return (
    <button onClick={handleClick} disabled={pending}>
      {pending ? 'Добавление...' : 'В корзину'}
    </button>
  );
}

Server Actions

// app/actions.ts
'use server';

import { db } from '@/lib/database';
import { revalidatePath } from 'next/cache';

export async function createPost(formData: FormData) {
  const title = formData.get('title') as string;
  const content = formData.get('content') as string;

  await db.post.create({
    data: { title, content }
  });

  revalidatePath('/posts');
}

// Использование в форме
export default function NewPostPage() {
  return (
    <form action={createPost}>
      <input name="title" placeholder="Заголовок" required />
      <textarea name="content" placeholder="Содержание" required />
      <button type="submit">Создать</button>
    </form>
  );
}

Streaming и Suspense

import { Suspense } from 'react';

export default function DashboardPage() {
  return (
    <div>
      <h1>Dashboard</h1>
      
      <Suspense fallback={<StatsSkeleton />}>
        <Stats />
      </Suspense>
      
      <Suspense fallback={<ChartSkeleton />}>
        <RevenueChart />
      </Suspense>
      
      <Suspense fallback={<TableSkeleton />}>
        <RecentOrders />
      </Suspense>
    </div>
  );
}

async function Stats() {
  const stats = await getStats();
  return <StatsGrid data={stats} />;
}

async function RevenueChart() {
  const data = await getRevenueData();
  return <Chart data={data} />;
}

Серверный рендеринг vs Клиентский компонент

Понимание разницы между серверным рендерингом и клиентским компонентом — ключ к эффективной архитектуре. Серверный рендеринг происходит на сервере, результат отправляется как HTML. Клиентский компонент требует JavaScript для работы.

Гидратация и производительность

Гидратация — процесс "оживления" серверного HTML на клиенте. Чем меньше клиентских компонентов, тем быстрее гидратация и лучше производительность.

Работа с базой данных

Server Components позволяют напрямую обращаться к базе данных без создания API endpoints. Используйте fetch для внешних API или ORM (Prisma, Drizzle) для базы данных. Кэширование запросов происходит автоматически.

Композиция компонентов

Правильная композиция — Server Components содержат Client Components, но не наоборот. Это позволяет минимизировать клиентский JavaScript и улучшить SEO.

Заключение

React Server Components — это не просто оптимизация, это новый способ думать о React-приложениях. Начните с простого правила: всё по умолчанию — Server Component, и добавляйте 'use client' только когда это действительно необходимо.

Server Components + Server Actions = полноценный fullstack на React без API routes.

ReactServer ComponentsNext.jsPerformance

Понравилась статья?

Подпишитесь на наш блог, чтобы не пропустить новые материалы