Next.js
Gyakorlati példák
// app/blog/page.tsx – Blog lista oldal
15. Gyakorlati példák
Blog alkalmazás
// app/blog/page.tsx – Blog lista oldal
import Link from 'next/link'
async function getPosts() {
'use cache'
cacheLife('hours')
cacheTag('posts')
return await db.posts.findAll({ published: true })
}
export default async function BlogPage() {
const posts = await getPosts()
return (
<main className="max-w-3xl mx-auto py-12 px-4">
<h1 className="text-4xl font-bold mb-8">Blog</h1>
<div className="space-y-6">
{posts.map(post => (
<article key={post.id} className="border-b pb-6">
<Link href={`/blog/${post.slug}`}>
<h2 className="text-2xl font-semibold hover:text-blue-600">
{post.title}
</h2>
</Link>
<p className="text-gray-600 mt-2">{post.excerpt}</p>
<time className="text-sm text-gray-400">{post.publishedAt}</time>
</article>
))}
</div>
</main>
)
}// app/blog/[slug]/page.tsx – Blog post oldal
import { notFound } from 'next/navigation'
export async function generateStaticParams() {
const posts = await db.posts.findAll()
return posts.map(p => ({ slug: p.slug }))
}
export async function generateMetadata({ params }) {
const { slug } = await params
const post = await db.posts.findBySlug(slug)
if (!post) return {}
return {
title: post.title,
description: post.excerpt,
}
}
export default async function BlogPost({ params }) {
const { slug } = await params
const post = await db.posts.findBySlug(slug)
if (!post) notFound()
return (
<article className="max-w-3xl mx-auto py-12 px-4 prose">
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.htmlContent }} />
</article>
)
}Autentikáció
// app/actions/auth.ts
'use server'
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'
export async function login(formData: FormData) {
const email = formData.get('email') as string
const password = formData.get('password') as string
const user = await verifyCredentials(email, password)
if (!user) {
return { error: 'Hibás email vagy jelszó' }
}
const token = await createSession(user.id)
const cookieStore = await cookies()
cookieStore.set('session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 60 * 60 * 24 * 7, // 1 hét
})
redirect('/dashboard')
}
export async function logout() {
const cookieStore = await cookies()
cookieStore.delete('session')
redirect('/login')
}// app/login/page.tsx
import { login } from '@/app/actions/auth'
export default function LoginPage() {
return (
<div className="min-h-screen flex items-center justify-center">
<form action={login} className="w-full max-w-sm space-y-4">
<h1 className="text-2xl font-bold">Bejelentkezés</h1>
<input
name="email"
type="email"
placeholder="Email cím"
className="w-full border rounded px-3 py-2"
required
/>
<input
name="password"
type="password"
placeholder="Jelszó"
className="w-full border rounded px-3 py-2"
required
/>
<button
type="submit"
className="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700"
>
Bejelentkezés
</button>
</form>
</div>
)
}Dashboard loading state-tel
// app/dashboard/page.tsx
import { Suspense } from 'react'
async function RecentOrders() {
const orders = await fetchRecentOrders() // lassú lekérés
return (
<ul>
{orders.map(o => <li key={o.id}>{o.title}</li>)}
</ul>
)
}
async function Stats() {
const stats = await fetchStats() // lassú lekérés
return (
<div className="grid grid-cols-3 gap-4">
<StatCard title="Bevétel" value={stats.revenue} />
<StatCard title="Rendelések" value={stats.orders} />
<StatCard title="Ügyfelek" value={stats.customers} />
</div>
)
}
export default function DashboardPage() {
return (
<div className="p-6 space-y-8">
<h1 className="text-3xl font-bold">Dashboard</h1>
<Suspense fallback={
<div className="grid grid-cols-3 gap-4">
{[1,2,3].map(i => <SkeletonCard key={i} />)}
</div>
}>
<Stats />
</Suspense>
<section>
<h2 className="text-xl font-semibold mb-4">Legutóbbi rendelések</h2>
<Suspense fallback={<OrdersSkeleton />}>
<RecentOrders />
</Suspense>
</section>
</div>
)
}API fetch Client Component-ből
'use client'
// components/SearchResults.tsx
import { useState, useEffect } from 'react'
export function SearchResults({ query }: { query: string }) {
const [results, setResults] = useState([])
const [loading, setLoading] = useState(false)
useEffect(() => {
if (!query) return
setLoading(true)
fetch(`/api/search?q=${encodeURIComponent(query)}`)
.then(res => res.json())
.then(data => {
setResults(data.results)
setLoading(false)
})
}, [query])
if (loading) return <p>Keresés...</p>
return (
<ul>
{results.map(r => (
<li key={r.id}>{r.title}</li>
))}
</ul>
)
}📝 Összefoglaló – 15. fejezet
- Blog:
generateStaticParams+"use cache"+revalidateTag= gyors, friss, SEO-barát - Auth: Server Actions +
cookies()+redirect()– biztonságos, szerver oldali folyamat - Dashboard: Streaming + Suspense = azonnali interaktivitás, nincs loading spinner az egész oldalra
- Client oldali fetch:
useEffect+ fetch API – akkor használd, ha valóban kliensnek kell