Next.js
Server Actions & API-k
Server Actions, useFormStatus, useActionState és Route Handlers áttekintése.
Next.js – Server Actions & API-k
A teljes Next.js jegyzet 8–9. fejezetének kivonata.
Mi az a Server Action?
- Szerver oldalon futó aszinkron függvény,
- közvetlenül hívható a kliensről (pl.
<form action={action}>), - nem kell hozzá külön REST endpoint.
// app/actions.ts
"use server";
import { db } from '@/lib/db';
import { revalidatePath } from 'next/cache';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
const content = formData.get('content') as string;
await db.insert(postsTable).values({ title, content });
revalidatePath('/blog');
}Használat form‑ban:
// app/blog/new/page.tsx
import { createPost } from '@/app/actions';
export default function NewPostPage() {
return (
<form action={createPost}>
<input type="text" name="title" required />
<textarea name="content" required />
<button type="submit">Közzétesz</button>
</form>
);
}useFormStatus – pending állapot
"use client";
import { useFormStatus } from 'react-dom';
function SubmitButton() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Küldés...' : 'Küldés'}
</button>
);
}Fontos: a SubmitButton‑t a <form> belsejébe kell tenni.
useActionState – eredmény & hiba kezelése
// actions.ts
"use server";
export async function createPost(prevState: any, formData: FormData) {
const title = formData.get('title') as string;
if (!title) return { error: 'A cím kötelező!' };
// ... mentés
return { success: true };
}"use client";
import { useActionState } from 'react';
import { createPost } from './actions';
export default function NewPostForm() {
const [state, formAction, isPending] = useActionState(createPost, null);
return (
<form action={formAction}>
<input name="title" />
{state?.error && <p style={{ color: 'red' }}>{state.error}</p>}
<button disabled={isPending}>{isPending ? 'Küldés...' : 'Küldés'}</button>
</form>
);
}Mikor jó a Server Action?
Használd, ha:
- form beküldés (login, regisztráció, CRUD),
- cache érvénytelenítés (
revalidatePath,revalidateTag), - redirect form után (
redirect).
Kerüld, ha:
- külső rendszereknek is kell hívni az endpointot → inkább Route Handler,
- nagyon sok helyről, sokféleképpen kell hívni → REST vagy RPC API jobban átlátható.
Route Handlers – API endpointok
Struktúra:
app/
└── api/
└── users/
└── route.ts → /api/users// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
const users = await db.select().from(usersTable);
return NextResponse.json(users);
}
export async function POST(request: Request) {
const body = await request.json();
const newUser = await db.insert(usersTable).values(body).returning();
return NextResponse.json(newUser[0], { status: 201 });
}Dinamikus route:
app/api/products/[id]/route.ts → /api/products/123import { NextRequest, NextResponse } from 'next/server';
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) {
const { id } = await params;
const product = await getProductById(id);
if (!product) {
return NextResponse.json({ error: 'Nem található' }, { status: 404 });
}
return NextResponse.json(product);
}Server Actions vs Route Handlers
| Helyzet | Ajánlott |
|---|---|
| Benti form, nincs külső kliens | Server Action |
| Nyilvános API‑t kell adni más rendszereknek | Route Handler |
| Egyszerű mutáció + cache frissítés | Server Action |
| Komplett CRUD, külső kliensekkel | Route Handlers (REST/RPC) |
Összefoglalás
- Server Action: a legegyszerűbb út formok kezelésére Next.js App Router‑ben.
useFormStatusésuseActionStatekényelmes UI‑t ad pending / hiba / siker állapothoz.- Route Handlers: klasszikus HTTP API endpointok, ha a világ felé is publikálnod kell az API‑t.