Čeština

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:

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í:

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í:

Použití validačních knihoven

Pro složitější scénáře validace zvažte použití validačních knihoven jako:

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í:

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í:

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í:

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:

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í:

Osvědčené postupy pro Server Actions

Chcete-li maximalizovat přínosy Server Actions, zvažte následující osvědčené postupy:

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:

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.