Пошук уроків, статей та іншого контенту
Як виконувати мутації даних напряму з форми, без ручного написання окремого API-ендпоінта.
У класичному підході форма на клієнті відправляє запит на окремий API-ендпоінт (наприклад, POST /api/todos), який приймає дані, валідує їх і оновлює базу даних — доводиться писати і клієнтський код відправки запиту, і серверний обробник, синхронізуючи їх вручну. Server Actions дозволяють описати серверну функцію-мутацію прямо поруч із компонентом і викликати її з форми напряму, без ручного проміжного API-шару.
Функція позначається директивою "use server" — або на початку окремого файлу (усі експортовані функції файлу стають Server Actions), або прямо всередині async-функції компонента для локальних дій:
// app/todos/actions.ts
"use server";
import { prisma } from "@/server/db/client";
import { revalidatePath } from "next/cache";
export async function createTodo(formData: FormData) {
const text = formData.get("text");
if (typeof text !== "string" || text.trim().length === 0) {
throw new Error("Текст завдання обов'язковий"); // валідація на сервері, не лише на клієнті
}
await prisma.todo.create({ data: { text } });
revalidatePath("/todos"); // без цього список не оновиться — сторінка й далі показує старий кеш
}Server Action передається напряму в атрибут action елемента <form> — React 19/Next.js автоматично викликає її при відправленні форми з об'єктом FormData, без потреби вручну писати fetch чи обробник onSubmit:
import { createTodo } from "./actions";
function NewTodoForm() {
return (
<form action={createTodo}>
<input name="text" placeholder="Нове завдання" />
<button type="submit">Додати</button>
</form>
);
}Форма зі Server Action як action працює навіть без завантаженого JavaScript на клієнті (progressive enhancement) — браузер відправить звичайний form submit, а Next.js обробить його на сервері. З увімкненим JavaScript та сама форма відправляється без повного перезавантаження сторінки.
Оскільки дані маршруту могли бути закешовані (стаття «Стратегії рендерингу»), після мутації потрібно явно повідомити Next.js, що кеш застарів — revalidatePath("/todos") інвалідує кеш конкретного шляху, revalidateTag("todos") — усі запити, позначені відповідним тегом, незалежно від шляху.
Server Action виконується на сервері, але клієнт технічно все одно може викликати її з довільними даними (наприклад, через змінений запит у DevTools) — тому вхідні дані так само потребують повної серверної валідації, як і будь-який традиційний API-ендпоінт; довіра лише клієнтській валідації форми небезпечна.
Забути revalidatePath/revalidateTag після мутації — дані в базі оновились, але кешована сторінка й далі показує старий вміст, поки кеш не спливе сам.
Довіряти лише клієнтській валідації форми (required, type="email") — Server Action усе одно потрібно перевіряти вхідні дані на сервері, оскільки її можна викликати напряму, обійшовши форму.
Писати Server Action, що виконує довгу, важку операцію синхронно в межах одного запиту форми — для справді довгих задач краще запускати фонову роботу й одразу повертати проміжний статус.
Server Actions — функції з директивою "use server", які виконуються на сервері, але викликаються прямо з клієнтської форми через action={fn} без ручного написання окремого API-ендпоінта, і працюють навіть без JavaScript на клієнті. Після мутації потрібно явно інвалідувати кеш через revalidatePath/revalidateTag, а вхідні дані завжди валідувати на сервері, незалежно від клієнтської валідації форми.