webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
Next.js · Lecția 8 din 12

Server Actions și formulare

Mutații sigure, useActionState, validare și UI optimist.

Actualizat

Ce este o Server Action

O Server Action e o funcție async marcată cu 'use server', pe care o apelezi din UI (un formular, un buton), dar care rulează pe server. Next creează automat un endpoint și face request-ul pentru tine.

Le folosești pentru mutații: creare, editare, ștergere, salvare. Înlocuiesc combinația „API route + fetch + loading state” pentru propriile formulare.

// features/create-post/api/create-post.ts
'use server'

import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'

export async function createPost(prev: State, formData: FormData) {
  const session = await auth()
  if (!session) return { error: 'Neautorizat' }

  const title = String(formData.get('title') ?? '').trim()
  if (title.length < 3) return { error: 'Titlul e prea scurt' }

  const post = await db.post.create({ data: { title, authorId: session.userId } })
  updateTag('posts')
  redirect(`/posts/${post.id}`)
}

Aplicația asta salvează progresul tău exact așa (entities/progress/api/save-progress.ts).

Securitate — cel mai important lucru

O Server Action e un endpoint POST public. Oricine o poate apela direct, fără UI-ul tău, cu ce date vrea.

  • Verifică autentificarea și autorizarea în fiecare acțiune („e logat?” și „are voie pe resursa asta?”).
  • Validează tot inputul (zod / valibot) — formData poate conține orice.
  • Nu returna date sensibile.

Moduri de a apela o Server Action

Mod Cod Când
<form action={fn}> primește FormData implicit pentru formulare; merge și fără JS
useActionState(fn, initial) primești [state, action, pending] afișezi erori / mesaje / pending
<button formAction={fn}> mai multe acțiuni într-un form „Salvează” vs „Șterge”
apel direct într-un handler await fn(args) interacțiuni care nu sunt formulare (like, salvare automată)

Formular cu useActionState

'use client'
import { useActionState } from 'react'

export function PostForm() {
  const [state, action, pending] = useActionState(createPost, { error: null })
  return (
    <form action={action}>
      <input name="title" required />
      <p aria-live="polite">{state.error}</p>
      <button disabled={pending}>{pending ? 'Se salvează…' : 'Salvează'}</button>
    </form>
  )
}

Cu useActionState, acțiunea primește state-ul anterior ca prim argument și FormData ca al doilea.

Progressive enhancement: un formular randat pe server cu o Server Action funcționează chiar dacă JS nu s-a încărcat încă.

Fluxul complet, cu validare Zod și valori păstrate după eroare, e în Formulare cu Server Actions.

UI optimist

const [optimisticLikes, addLike] = useOptimistic(likes, (state, n: number) => state + n)

<form action={async () => { addLike(1); await like(postId) }}>

UI-ul se schimbă instant; dacă acțiunea eșuează, React revine la valoarea reală.

Server Action vs Route Handler

Server Action Route Handler
formulare și butoane din aplicația ta API consumat de alții (mobile, parteneri)
mutații webhooks (Stripe, CMS)
apelate secvențial, una câte una răspunsuri non-HTML (RSS, fișiere, JSON public)

Citirea datelor nu se face prin Server Actions — pentru asta există Server Components.

Pe scurt

  • Server Action = funcție 'use server' apelată din UI, rulată pe server; pentru mutații.
  • Fiecare acțiune: auth + autorizare + validare.
  • <form action> + useActionState pentru erori și pending; updateTag după mutație.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.