Skip to Content
Docs▲ Next.jsData Fetching

Data Fetching în Next.js

Next.js App Router oferă mai multe modalități de a obține date, fiecare cu scopul ei.

Server Components (recomandat)

În App Router, toate componentele sunt Server Components by default. Poți face fetch direct în ele — fără useEffect, fără loading state manual.

// app/posts/page.jsx — rulează pe server, nu în browser export default async function PostsPage() { const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5') const posts = await res.json() return ( <ul> {posts.map(post => ( <li key={post.id}> <strong>{post.title}</strong> <p>{post.body}</p> </li> ))} </ul> ) }

Nu ai nevoie de useState sau useEffect. Componenta este async și await-ezi direct datele. Codul rulează pe server, deci API keys și date sensibile nu ajung în browser.

Caching și Revalidare

Next.js extinde fetch cu opțiuni de caching:

// Date cache-uite indefinit (default la build time) const res = await fetch('https://api.example.com/data', { cache: 'force-cache' })

Date dinamice per pagină

// app/posts/[id]/page.jsx export default async function PostPage({ params }) { const { id } = await params const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`) const post = await res.json() return ( <article> <h1>{post.title}</h1> <p>{post.body}</p> </article> ) }

generateStaticParams — pre-generare la build

// Generează static paginile /posts/1, /posts/2, ... /posts/10 export async function generateStaticParams() { const posts = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10').then(r => r.json()) return posts.map(post => ({ id: String(post.id), })) }

Client Components

Când ai nevoie de interactivitate (filtre, paginare, căutare în timp real), fetch-ul se face în Client Components:

'use client' import { useState, useEffect } from 'react' export default function SearchPosts() { const [query, setQuery] = useState('') const [posts, setPosts] = useState([]) const [loading, setLoading] = useState(false) useEffect(() => { if (!query) return setLoading(true) fetch(`/api/posts?q=${query}`) .then(r => r.json()) .then(data => { setPosts(data) setLoading(false) }) }, [query]) return ( <div> <input value={query} onChange={e => setQuery(e.target.value)} placeholder="Caută..." /> {loading && <p>Se caută...</p>} <ul> {posts.map(p => <li key={p.id}>{p.title}</li>)} </ul> </div> ) }

Route Handlers (API Routes)

Creează endpoint-uri API în app/api/:

// app/api/posts/route.js import { NextResponse } from 'next/server' const posts = [ { id: 1, title: 'Primul articol' }, { id: 2, title: 'Al doilea articol' }, ] export async function GET(request) { const { searchParams } = new URL(request.url) const q = searchParams.get('q') ?? '' const filtered = posts.filter(p => p.title.toLowerCase().includes(q.toLowerCase()) ) return NextResponse.json(filtered) } export async function POST(request) { const body = await request.json() const newPost = { id: Date.now(), title: body.title } posts.push(newPost) return NextResponse.json(newPost, { status: 201 }) }

Nu apela Route Handlers din Server Components! Fă fetch direct la baza de date sau serviciu — elimini un round-trip inutil de rețea.

Pattern recomandat: Separarea responsabilităților

Server Component — aduce datele

// app/dashboard/page.jsx import { StatsClient } from './StatsClient' async function getStats() { const res = await fetch('https://api.example.com/stats', { next: { revalidate: 300 } }) return res.json() } export default async function DashboardPage() { const stats = await getStats() return <StatsClient initialData={stats} /> }

Client Component — gestionează interactivitatea

// app/dashboard/StatsClient.jsx 'use client' import { useState } from 'react' export function StatsClient({ initialData }) { const [data, setData] = useState(initialData) return ( <div> <p>Vizitatori: {data.visitors}</p> <button onClick={() => fetch('/api/stats').then(r => r.json()).then(setData)}> Actualizează </button> </div> ) }

Astfel obții cel mai bun din ambele lumi: randare rapidă pe server + interactivitate pe client.

Last updated on