webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
Next.js · Lecția 6 din 12

Data fetching și streaming

Date direct în Server Components, paralel, Suspense și params ca Promise.

Actualizat

Ce înseamnă data fetching în Next

Data fetching = aducerea datelor (din DB, dintr-un API) de care are nevoie pagina. În Next App Router, locul implicit e Server Component-ul: o funcție async care citește datele direct și randează rezultatul.

export default async function Page() {
  const posts = await db.post.findMany()       // ORM, SQL, fetch — orice
  return <PostList posts={posts} />
}

Comparat cu varianta clasică React (useEffect + fetch + useState): fără loading state pe client, fără API route intermediar, fără secrete expuse, fără waterfall client → server → DB.

Moduri de a aduce date — și când

Mod Unde Când
await direct în Server Component server implicit — orice afișare de date
Promise trimis la Client Component + use() server pornește, client citește componenta client are nevoie de date, dar vrei streaming
TanStack Query client date foarte interactive (polling, infinite scroll) — Server state
Route Handler server API pentru alții / webhooks — nu pentru propriile pagini
useEffect + fetch client aproape niciodată

Paralel, nu cascadă

Waterfall = request-uri care așteaptă unul după altul fără motiv.

// ✗ waterfall — 2 × timpul
const user = await getUser(id)
const posts = await getPosts(id)

// ✓ paralel
const [user, posts] = await Promise.all([getUser(id), getPosts(id)])

Ce este streaming

Fără streaming, userul vede pagina abia când toate datele sunt gata. Cu streaming, serverul trimite HTML-ul pe bucăți: ce e gata apare imediat, părțile lente vin când termină.

Instrumentul: <Suspense>.

export default function Page() {
  return (
    <>
      <Header />                                   {/* apare imediat */}
      <Suspense fallback={<Skeleton />}>
        <Recommendations />                        {/* async, apare când e gata */}
      </Suspense>
    </>
  )
}

loading.tsx = un <Suspense> automat în jurul întregii pagini.

Promise trimis la client

Pornești request-ul pe server, dar îl citești într-un Client Component:

// server
const statsPromise = getStats()                  // fără await — nu blochează
<Suspense fallback={<Spinner />}>
  <Stats data={statsPromise} />
</Suspense>

// client
'use client'
import { use } from 'react'
export function Stats({ data }: { data: Promise<Stats> }) {
  const stats = use(data)                        // suspendă până vine
}

Date de runtime

cookies(), headers(), searchParams, params (pentru valori nepre-generate) depind de request — nu pot fi știute la build. Componentele care le citesc devin dinamice și trebuie puse în <Suspense>, ca restul paginii să rămână static. Exact așa e afișat progresul tău în aplicația asta.

Deduplicare

Aceeași funcție chemată din layout + page + generateMetadata?

Unealtă Durată
cache() din React pe durata unui request
'use cache' persistent, între request-uri — lecția Cache

Pe scurt

  • Date → direct în Server Components, cu await.
  • Promise.all pentru request-uri independente.
  • <Suspense> pentru streaming; datele de runtime stau în Suspense.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.