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

Отримання даних у Next.js

У маршрутизаторі додатка (App Router) отримання даних відбувається безпосередньо в серверних компонентах. Не потрібні спеціальні функції, такі як getServerSideProps або getStaticProps. Компонент просто await запит.

Отримання даних у серверних компонентах

tsx
// app/problems/page.tsx import { db } from '@/lib/db' export default async function ProblemsPage() { const problems = await db.problem.findMany({ orderBy: { difficulty: 'asc' } }) return ( <ul> {problems.map(p => ( <li key={p.id}>{p.name}</li> ))} </ul> ) }

Серверний компонент може безпосередньо отримувати доступ до бази даних, файлової системи або зовнішніх API. Код і залежності не включені до клієнтського бандлу.

fetch з кешуванням

Next.js розширює стандартний fetch, додаючи кешування та повторну валідацію:

tsx
// Кешується за замовчуванням (еквівалент SSG) const res = await fetch('https://api.itlead.org/docs') // Без кешування (еквівалент SSR) const res = await fetch('https://api.itlead.org/feed', { cache: 'no-store' }) // Повторна валідація на основі часу (еквівалент ISR) const res = await fetch('https://api.itlead.org/problems', { next: { revalidate: 300 } }) // Повторна валідація на основі тегів const res = await fetch('https://api.itlead.org/problems', { next: { tags: ['problems'] } })

Паралельне отримання даних

Звичайна помилка: послідовні запити, які могли б виконуватись паралельно.

tsx
// Погано: послідовні запити export default async function DashboardPage() { const user = await getUser() const stats = await getStats() // чекає на getUser const activity = await getActivity() // чекає на getStats // ... } // Добре: паралельні запити export default async function DashboardPage() { const [user, stats, activity] = await Promise.all([ getUser(), getStats(), getActivity() ]) // ... }

Шаблон: Попереднє завантаження даних

Для паралельного завантаження на рівні дерева компонентів використовуйте шаблон попереднього завантаження:

tsx
// lib/problems.ts import { cache } from 'react' export const getProblems = cache(async () => { const res = await fetch('https://api.itlead.org/problems') return res.json() }) export function preloadProblems() { void getProblems() }
tsx
// app/problems/page.tsx import { getProblems, preloadProblems } from '@/lib/problems' import { ProblemList } from './problem-list' export default async function ProblemsPage() { preloadProblems() return <ProblemList /> }

React.cache гарантує, що запит виконується лише один раз, навіть якщо getProblems викликається в кількох місцях.

Отримання даних на стороні клієнта

Для інтерактивних сценаріїв (пошук, фільтрація) дані завантажуються на стороні клієнта:

tsx
'use client' import { useEffect, useState } from 'react' export function ProblemSearch() { const [query, setQuery] = useState('') const [results, setResults] = useState([]) useEffect(() => { if (!query) return const controller = new AbortController() fetch(`/api/search?q=${query}`, { signal: controller.signal }) .then(res => res.json()) .then(setResults) return () => controller.abort() }, [query]) return ( <div> <input value={query} onChange={e => setQuery(e.target.value)} /> <ul>{results.map(r => <li key={r.id}>{r.name}</li>)}</ul> </div> ) }

Практична порада:

Завантажуйте початкові дані на сервері та передавайте їх до клієнтських компонентів через пропси. Використовуйте отримання даних на стороні клієнта лише для даних, які залежать від дій користувача.

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

Суміжні теми

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

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

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

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