Next.js
Adatlekérés (fetch, Server Actions)
A legegyszerűbb és leghatékonyabb módszer: async Server Component:
6. Adatlekérés (fetch, Server Actions)
Server oldali adatlekérés
A legegyszerűbb és leghatékonyabb módszer: async Server Component:
// app/products/page.tsx
async function getProducts() {
const res = await fetch('https://api.example.com/products', {
next: { revalidate: 3600 }, // ISR: 1 óránként frissül
})
if (!res.ok) throw new Error('Fetch sikertelen')
return res.json()
}
export default async function ProductsPage() {
const products = await getProducts()
return (
<ul>
{products.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
)
}Cache opciók fetch-nél
// Statikus – build időben egyszer lekéri, cache-eli
fetch(url, { cache: 'force-cache' })
// Dinamikus – minden kérésnél frissen lekéri
fetch(url, { cache: 'no-store' })
// ISR – megadott időnként frissül
fetch(url, { next: { revalidate: 60 } }) // 60 másodpercenként
// Tag alapú revalidálás
fetch(url, { next: { tags: ['products'] } })Server Actions
A Server Actions szerveren futó függvények, amelyeket kliens komponensekből lehet meghívni – form submission, mutation, stb.
// app/actions.ts
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost(formData: FormData) {
const title = formData.get('title') as string
const content = formData.get('content') as string
// Adatbázis írás
await db.posts.create({ title, content })
// Cache invalidálás
revalidateTag('posts')
}// app/new-post/page.tsx – Server Component
import { createPost } from '@/app/actions'
export default function NewPostPage() {
return (
<form action={createPost}>
<input name="title" placeholder="Cím" required />
<textarea name="content" placeholder="Tartalom" required />
<button type="submit">Közzétesz</button>
</form>
)
}Server Action Client Component-ből
'use client'
import { useTransition } from 'react'
import { createPost } from '@/app/actions'
export default function NewPostForm() {
const [isPending, startTransition] = useTransition()
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const formData = new FormData(e.currentTarget)
startTransition(async () => {
await createPost(formData)
})
}
return (
<form onSubmit={handleSubmit}>
<input name="title" placeholder="Cím" />
<button type="submit" disabled={isPending}>
{isPending ? 'Mentés...' : 'Közzétesz'}
</button>
</form>
)
}Párhuzamos adatlekérés
export default async function DashboardPage() {
// ❌ Szekvenciális – lassú
const user = await fetchUser()
const posts = await fetchPosts()
// ✅ Párhuzamos – gyors
const [user, posts] = await Promise.all([
fetchUser(),
fetchPosts(),
])
return <Dashboard user={user} posts={posts} />
}Loading UI és Suspense
// app/blog/loading.tsx – automatikusan megjelenik adatlekérés alatt
export default function Loading() {
return <div className="animate-pulse">Betöltés...</div>
}// Manuális Suspense – granulálisabb control
import { Suspense } from 'react'
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<Skeleton />}>
<SlowDataComponent />
</Suspense>
</div>
)
}📝 Összefoglaló – 6. fejezet
- Server Component-ekben async/await-tel közvetlenül lekérhetsz adatot, nincs szükség useEffect-re
- A
fetchAPI kiterjesztve cache opciókkal:force-cache,no-store,revalidate - Server Actions szerveren futó mutációkat tesznek lehetővé form-okból és Client Componentekből
- A
Promise.allpárhuzamosítja az adatlekéréseket – mindig ezt használd, ha lehetséges - A vízesések elkerülése, a Suspense és a
React.cache()részletesen a következő fejezetben van