Skip to main content
Практика завдань

Як працює рендеринг на стороні клієнта (CSR) у Next.js

CSR (Рендеринг на стороні клієнта) — це підхід, при якому рендеринг сторінки відбувається повністю в браузері. Сервер надсилає мінімальний HTML з пакетом JavaScript, а React рендерить контент на стороні клієнта.

У звичайному додатку React (без Next.js) весь рендеринг відбувається на стороні клієнта. У Next.js CSR також доступний, але використовується вибірково для частин інтерфейсу, які потребують інтерактивності або даних, доступних лише в браузері.

Коли CSR Використовується в Next.js

У Next.js немає сторінок, які працюють повністю через CSR (як звичайний SPA на React). Компонент сервера завжди рендерить початковий HTML. Але всередині сторінки можуть бути клієнтські компоненти, які завантажують дані та рендерять контент на клієнті.

Типові сценарії:

  • Завантаження даних на основі дій користувача (фільтри, пошук)
  • Компоненти, що використовують API браузера (localStorage, геолокація)
  • Інтерактивні віджети (чат, сповіщення, таймери)

Як Це Реалізувати

Завантаження Даних у Клієнтському Компоненті

tsx
'use client' import { useState, useEffect } from 'react' interface Problem { id: string name: string difficulty: number } export default function ProblemSearch() { const [query, setQuery] = useState('') const [results, setResults] = useState<Problem[]>([]) const [loading, setLoading] = useState(false) useEffect(() => { if (!query) { setResults([]) return } setLoading(true) const controller = new AbortController() fetch(`/api/problems/search?q=${query}`, { signal: controller.signal }) .then(res => res.json()) .then(data => setResults(data)) .finally(() => setLoading(false)) return () => controller.abort() }, [query]) return ( <div> <input value={query} onChange={e => setQuery(e.target.value)} placeholder="Пошук задач на IT Lead" /> {loading && <p>Завантаження...</p>} <ul> {results.map(p => ( <li key={p.id}>{p.name}</li> ))} </ul> </div> ) }

Динамічний Імпорт з Вимкненим SSR

Іноді компонент не може бути рендерений на сервері взагалі (використовує window, document тощо). У таких випадках ви можете вимкнути SSR для конкретного компонента:

tsx
import dynamic from 'next/dynamic' const CodeEditor = dynamic( () => import('@/components/ide/code-editor'), { ssr: false, loading: () => <p>Завантаження редактора...</p> } ) export default function ProblemPage() { return ( <div> <h1>Задача з JavaScript</h1> <CodeEditor /> </div> ) }

ssr: false гарантує, що компонент буде завантажено та рендерено лише в браузері.

Шаблон: Обгортка Сервера + Інтерактивність Клієнта

Правильний підхід у Next.js: завантажити початкові дані на сервері та реалізувати інтерактивність на клієнті:

tsx
// app/problems/page.tsx (компонент сервера) import { db } from '@/lib/db' import { ProblemFilter } from './problem-filter' export default async function ProblemsPage() { const problems = await db.problem.findMany({ select: { id: true, name: true, difficulty: true } }) return ( <div> <h1>Задачі</h1> <ProblemFilter initialProblems={problems} /> </div> ) }
tsx
// app/problems/problem-filter.tsx (клієнтський компонент) 'use client' import { useState } from 'react' interface Problem { id: string name: string difficulty: number } export function ProblemFilter({ initialProblems }: { initialProblems: Problem[] }) { const [difficulty, setDifficulty] = useState<number | null>(null) const filtered = difficulty ? initialProblems.filter(p => p.difficulty === difficulty) : initialProblems return ( <div> <div> <button onClick={() => setDifficulty(null)}>Всі</button> <button onClick={() => setDifficulty(1)}>Легкі</button> <button onClick={() => setDifficulty(2)}>Середні</button> <button onClick={() => setDifficulty(3)}>Важкі</button> </div> <ul> {filtered.map(p => ( <li key={p.id}>{p.name}</li> ))} </ul> </div> ) }

Ключовий принцип:

У Next.js CSR застосовується до окремих компонентів, а не до всіх сторінок. Початковий HTML завжди надходить з сервера, що забезпечує хорошу SEO та швидке перше завантаження. Інтерактивність додається поверх.

Недоліки Чистого CSR

  • SEO. Контент, що рендериться лише на клієнті, невидимий для пошукових ботів, поки не виконається JavaScript.
  • Перше завантаження. Користувач бачить порожню сторінку або скелет, поки JavaScript завантажується та виконується.
  • Продуктивність на слабких пристроях. Весь рендеринг лягає на процесор пристрою користувача.

Саме тому Next.js за замовчуванням використовує серверні компоненти, а CSR застосовується лише там, де це необхідно.

Корисні Ресурси

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань