Дії сервера в Next.js
Дії на сервері — це асинхронні функції, які виконуються на сервері. Вони дозволяють змінювати дані (створювати, оновлювати, видаляти) безпосередньо з компонентів, не створюючи окремі API кінцеві точки.
Як визначити Дію на сервері
Дія на сервері — це функція, позначена директивою 'use server':
// actions/problem.ts
'use server'
import { db } from '@/lib/db'
import { revalidatePath } from 'next/cache'
export async function solveProblem(problemId: string, userId: string) {
await db.user.update({
where: { id: userId },
data: {
solvedProblems: { push: problemId }
}
})
revalidatePath('/problems')
}Директиву можна встановити на рівні файлу (як вище) або на рівні окремої функції:
export default async function Page() {
async function handleSubmit(formData: FormData) {
'use server'
const name = formData.get('name')
await db.user.update({ where: { id: userId }, data: { name } })
}
return <form action={handleSubmit}>...</form>
}Використання з формами
Дії на сервері можна передавати безпосередньо в action форми. Форма працює навіть без JavaScript на стороні клієнта (прогресивне покращення):
// app/settings/page.tsx
import { db } from '@/lib/db'
import { revalidatePath } from 'next/cache'
export default async function SettingsPage() {
async function updateProfile(formData: FormData) {
'use server'
const name = formData.get('name') as string
await db.user.update({
where: { id: currentUserId },
data: { name }
})
revalidatePath('/settings')
}
return (
<form action={updateProfile}>
<input name="name" placeholder="Ім'я на IT Lead" />
<button type="submit">Зберегти</button>
</form>
)
}Використання з useTransition
Для оптимістичних оновлень і вказівки завантаження:
'use client'
import { useTransition } from 'react'
import { solveProblem } from '@/actions/problem'
export function SolveButton({
problemId,
userId
}: {
problemId: string
userId: string
}) {
const [isPending, startTransition] = useTransition()
return (
<button
disabled={isPending}
onClick={() => {
startTransition(() => solveProblem(problemId, userId))
}}
>
{isPending ? 'Перевірка...' : 'Вирішено'}
</button>
)
}Валідація даних
Дії на сервері отримують введення користувача, тому валідація є обов'язковою:
'use server'
import { z } from 'zod'
const schema = z.object({
name: z.string().min(2).max(50),
email: z.string().email()
})
export async function updateUser(formData: FormData) {
const result = schema.safeParse({
name: formData.get('name'),
email: formData.get('email')
})
if (!result.success) {
return { error: result.error.flatten().fieldErrors }
}
await db.user.update({
where: { id: currentUserId },
data: result.data
})
revalidatePath('/settings')
return { success: true }
}Повторна валідація після зміни
Після зміни даних потрібно оновити кеш:
'use server'
import { revalidatePath, revalidateTag } from 'next/cache'
import { redirect } from 'next/navigation'
export async function createProblem(data: ProblemData) {
await db.problem.create({ data })
revalidateTag('problems') // інвалідовує кеш даних за тегом
revalidatePath('/problems') // інвалідовує кеш повного маршруту
redirect('/problems') // перенаправляє після створення
}Порада для інтерв'ю:
Дії на сервері не є заміною REST API. Вони призначені для мутацій даних з UI. Для публічних API, інтеграцій з іншими сервісами або вебхуками використовуйте обробники маршрутів.
Корисні ресурси
- nextjs.org/docs — Дії на сервері
- Форми та мутації
Суміжні теми
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.