Komplexní průvodce Next.js 14 Server Actions. Pokrývá osvědčené postupy pro formuláře, validaci dat, bezpečnost a pokročilé techniky pro moderní webové aplikace.
Next.js 14 Server Actions: Zvládnutí osvědčených postupů pro zpracování formulářů
Next.js 14 přináší výkonné funkce pro tvorbu výkonných a uživatelsky přívětivých webových aplikací. Mezi nimi vynikají Server Actions jako transformační způsob, jak zpracovávat odesílání formulářů a datové mutace přímo na serveru. Tento průvodce poskytuje komplexní přehled Server Actions v Next.js 14, zaměřený na osvědčené postupy pro zpracování formulářů, validaci dat, bezpečnost a pokročilé techniky. Prozkoumáme praktické příklady a poskytneme užitečné poznatky, které vám pomohou vytvářet robustní a škálovatelné webové aplikace.
Co jsou Next.js Server Actions?
Server Actions jsou asynchronní funkce, které běží na serveru a mohou být volány přímo z React komponent. Eliminují potřebu tradičních API cest pro zpracování odesílání formulářů a datových mutací, což vede ke zjednodušenému kódu, lepší bezpečnosti a zvýšenému výkonu. Server Actions jsou React Server Components (RSC), což znamená, že jsou prováděny na serveru, což vede k rychlejšímu počátečnímu načítání stránek a lepšímu SEO.
Klíčové výhody Server Actions:
- Zjednodušený kód: Omezte opakující se kód eliminací potřeby samostatných API cest.
- Zvýšená bezpečnost: Provádění na straně serveru minimalizuje zranitelnosti na straně klienta.
- Zvýšený výkon: Provádějte datové mutace přímo na serveru pro rychlejší odezvu.
- Optimalizované SEO: Využijte server-side rendering pro lepší indexaci vyhledávači.
- Typová bezpečnost: Využijte end-to-end typovou bezpečnost s TypeScriptem.
Nastavení vašeho projektu Next.js 14
Než se ponoříte do Server Actions, ujistěte se, že máte nastavený projekt Next.js 14. Pokud začínáte od nuly, vytvořte nový projekt pomocí následujícího příkazu:
npx create-next-app@latest my-next-app
Ujistěte se, že váš projekt používá adresářovou strukturu app
, abyste mohli plně využít Server Components a Actions.
Základní zpracování formulářů se Server Actions
Začněme jednoduchým příkladem: formulář, který odesílá data pro vytvoření nové položky v databázi. Použijeme jednoduchý formulář s jedním vstupním polem a odesílacím tlačítkem.
Příklad: Vytvoření nové položky
Nejprve definujte funkci Server Action ve vaší React komponentě. Tato funkce bude zpracovávat logiku odeslání formuláře na serveru.
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
// Simulace interakce s databází
console.log('Vytváří se položka:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulace latence
console.log('Položka úspěšně vytvořena!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
await createItem(formData);
setIsSubmitting(false);
}
return (
);
}
Vysvětlení:
- Direktiva
'use client'
označuje, že se jedná o klientskou komponentu. - Funkce
createItem
je označena direktivou'use server'
, což znamená, že se jedná o Server Action. - Funkce
handleSubmit
je funkce na straně klienta, která volá serverovou akci. Také zpracovává stav UI, jako je deaktivace tlačítka během odesílání. - Vlastnost
action
elementu<form>
je nastavena na funkcihandleSubmit
. - Metoda
formData.get('name')
získává hodnotu vstupního pole 'name'. await new Promise
simuluje databázovou operaci a přidává latenci.
Validace dat
Validace dat je klíčová pro zajištění integrity dat a prevenci bezpečnostních zranitelností. Server Actions poskytují vynikající příležitost k provádění validace na straně serveru. Tento přístup pomáhá zmírnit rizika spojená pouze s validací na straně klienta.
Příklad: Validace vstupních dat
Upravte Server Action createItem
tak, aby obsahovala validační logiku.
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
if (!name || name.length < 3) {
throw new Error('Název položky musí mít alespoň 3 znaky.');
}
// Simulace interakce s databází
console.log('Vytváří se položka:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulace latence
console.log('Položka úspěšně vytvořena!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Došlo k chybě.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Vysvětlení:
- Funkce
createItem
nyní kontroluje, zda jename
platné (alespoň 3 znaky dlouhé). - Pokud validace selže, je vyhozena chyba.
- Funkce
handleSubmit
je aktualizována tak, aby zachytila jakékoli chyby vyhozené Server Action a zobrazila chybovou zprávu uživateli.
Použití validačních knihoven
Pro složitější scénáře validace zvažte použití validačních knihoven jako:
- Zod: TypeScript-first knihovna pro deklaraci schémat a validaci.
- Yup: JavaScript schema builder pro parsování, validaci a transformaci hodnot.
Zde je příklad s použitím Zod:
// app/utils/validation.ts
import { z } from 'zod';
export const CreateItemSchema = z.object({
name: z.string().min(3, 'Název položky musí mít alespoň 3 znaky.'),
});
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { CreateItemSchema } from '../utils/validation';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
const validatedFields = CreateItemSchema.safeParse({ name });
if (!validatedFields.success) {
return { errors: validatedFields.error.flatten().fieldErrors };
}
// Simulace interakce s databází
console.log('Vytváří se položka:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulace latence
console.log('Položka úspěšně vytvořena!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Došlo k chybě.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Vysvětlení:
CreateItemSchema
definuje validační pravidla pro polename
pomocí Zod.- Metoda
safeParse
se pokusí validovat vstupní data. Pokud validace selže, vrátí objekt s chybami. - Objekt
errors
obsahuje podrobné informace o selháních validace.
Bezpečnostní aspekty
Server Actions zvyšují bezpečnost prováděním kódu na serveru, ale stále je klíčové dodržovat osvědčené bezpečnostní postupy pro ochranu vaší aplikace před běžnými hrozbami.
Prevence Cross-Site Request Forgery (CSRF)
Útoky CSRF zneužívají důvěry, kterou webová stránka má v prohlížeči uživatele. K zabránění útokům CSRF implementujte mechanismy ochrany proti CSRF.
Next.js automaticky řeší ochranu proti CSRF při použití Server Actions. Framework generuje a validuje CSRF token pro každé odeslání formuláře, čímž zajišťuje, že požadavek pochází z vaší aplikace.
Zpracování autentizace a autorizace uživatelů
Zajistěte, aby pouze autorizovaní uživatelé mohli provádět určité akce. Implementujte mechanismy autentizace a autorizace pro ochranu citlivých dat a funkcí.
Zde je příklad použití NextAuth.js k ochraně Server Action:
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { getServerSession } from 'next-auth';
import { authOptions } from '../../app/api/auth/[...nextauth]/route';
async function createItem(formData: FormData) {
'use server'
const session = await getServerSession(authOptions);
if (!session) {
throw new Error('Neautorizováno');
}
const name = formData.get('name') as string;
// Simulace interakce s databází
console.log('Vytváří se položka:', name, 'uživatelem:', session.user?.email);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulace latence
console.log('Položka úspěšně vytvořena!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Došlo k chybě.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Vysvětlení:
- Funkce
getServerSession
získává informace o session uživatele. - Pokud uživatel není autentizován (nemá session), je vyhozena chyba, která zabrání provedení Server Action.
Sanitizace vstupních dat
Sanitizujte vstupní data, abyste předešli útokům Cross-Site Scripting (XSS). K útokům XSS dochází, když je do webové stránky vložen škodlivý kód, což může ohrozit data uživatelů nebo funkčnost aplikace.
Použijte knihovny jako DOMPurify
nebo sanitize-html
k sanitizaci vstupů poskytnutých uživatelem před jejich zpracováním ve vašich Server Actions.
Pokročilé techniky
Nyní, když jsme probrali základy, prozkoumejme některé pokročilé techniky pro efektivní používání Server Actions.
Optimistické aktualizace
Optimistické aktualizace poskytují lepší uživatelský zážitek tím, že okamžitě aktualizují UI, jako by akce měla uspět, ještě předtím, než to server potvrdí. Pokud akce na serveru selže, UI se vrátí do původního stavu.
// app/components/UpdateItemForm.tsx
'use client';
import { useState } from 'react';
async function updateItem(id: string, formData: FormData) {
'use server'
const name = formData.get('name') as string;
// Simulace interakce s databází
console.log('Aktualizuje se položka:', id, 's názvem:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulace latence
// Simulace selhání (pro demonstrační účely)
const shouldFail = Math.random() < 0.5;
if (shouldFail) {
throw new Error('Aktualizace položky selhala.');
}
console.log('Položka úspěšně aktualizována!');
return { name }; // Vraťte aktualizovaný název
}
export default function UpdateItemForm({ id, initialName }: { id: string; initialName: string }) {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
const [itemName, setItemName] = useState(initialName);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
// Optimisticky aktualizovat UI
const newName = formData.get('name') as string;
setItemName(newName);
try {
const result = await updateItem(id, formData);
//Při úspěchu se aktualizace již projevila v UI pomocí setItemName
} catch (error: any) {
setErrorMessage(error.message || 'Došlo k chybě.');
// Vrátit UI zpět při chybě
setItemName(initialName);
} finally {
setIsSubmitting(false);
}
}
return (
Současný název: {itemName}
{errorMessage && {errorMessage}
}
);
}
Vysvětlení:
- Před zavoláním Server Action je UI okamžitě aktualizováno novým názvem položky pomocí
setItemName
. - Pokud Server Action selže, UI se vrátí k původnímu názvu položky.
Revalidace dat
Poté, co Server Action upraví data, může být potřeba revalidovat data v mezipaměti, aby se zajistilo, že UI odráží nejnovější změny. Next.js poskytuje několik způsobů revalidace dat:
- Revalidate Path: Revaliduje mezipaměť pro specifickou cestu.
- Revalidate Tag: Revaliduje mezipaměť pro data spojená se specifickým tagem.
Zde je příklad revalidace cesty po vytvoření nové položky:
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { revalidatePath } from 'next/cache';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
// Simulace interakce s databází
console.log('Vytváří se položka:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulace latence
console.log('Položka úspěšně vytvořena!');
revalidatePath('/items'); // Revalidovat cestu /items
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Došlo k chybě.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Vysvětlení:
- Funkce
revalidatePath('/items')
zneplatní mezipaměť pro cestu/items
, čímž zajistí, že další požadavek na tuto cestu načte nejnovější data.
Osvědčené postupy pro Server Actions
Chcete-li maximalizovat přínosy Server Actions, zvažte následující osvědčené postupy:
- Udržujte Server Actions malé a zaměřené: Server Actions by měly provádět jediný, dobře definovaný úkol. Vyhněte se složité logice uvnitř Server Actions, abyste zachovali čitelnost a testovatelnost.
- Používejte popisné názvy: Dávejte svým Server Actions popisné názvy, které jasně naznačují jejich účel.
- Zpracovávejte chyby elegantně: Implementujte robustní zpracování chyb, abyste poskytli uživateli informativní zpětnou vazbu a předešli pádům aplikace.
- Důkladně validujte data: Provádějte komplexní validaci dat, abyste zajistili jejich integritu a předešli bezpečnostním zranitelnostem.
- Zabezpečte své Server Actions: Implementujte mechanismy autentizace a autorizace pro ochranu citlivých dat a funkcí.
- Optimalizujte výkon: Sledujte výkon svých Server Actions a optimalizujte je podle potřeby, abyste zajistili rychlou odezvu.
- Využívejte efektivně mezipaměť: Využijte mechanismy mezipaměti Next.js ke zlepšení výkonu a snížení zátěže databáze.
Běžné nástrahy a jak se jim vyhnout
Ačkoli Server Actions nabízejí četné výhody, existují některé běžné nástrahy, na které je třeba si dát pozor:
- Příliš složité Server Actions: Nevkládejte příliš mnoho logiky do jedné Server Action. Rozdělte složité úkoly na menší, lépe spravovatelné funkce.
- Zanedbávání zpracování chyb: Vždy zahrňte zpracování chyb pro zachycení neočekávaných chyb a poskytnutí užitečné zpětné vazby uživateli.
- Ignorování bezpečnostních osvědčených postupů: Dodržujte osvědčené bezpečnostní postupy k ochraně vaší aplikace před běžnými hrozbami jako XSS a CSRF.
- Zapomínání na revalidaci dat: Ujistěte se, že revalidujete data v mezipaměti poté, co Server Action upraví data, aby bylo UI aktuální.
Závěr
Next.js 14 Server Actions poskytují výkonný a efektivní způsob, jak zpracovávat odesílání formulářů a datové mutace přímo na serveru. Dodržováním osvědčených postupů uvedených v tomto průvodci můžete vytvářet robustní, bezpečné a výkonné webové aplikace. Využijte Server Actions ke zjednodušení kódu, zvýšení bezpečnosti a zlepšení celkového uživatelského zážitku. Při integraci těchto principů zvažte globální dopad svých vývojových rozhodnutí. Zajistěte, aby vaše formuláře a procesy zpracování dat byly přístupné, bezpečné a uživatelsky přívětivé pro různorodé mezinárodní publikum. Tento závazek k inkluzivitě nejen zlepší použitelnost vaší aplikace, ale také rozšíří její dosah a efektivitu v globálním měřítku.