Пошук уроків, статей та іншого контенту
Розберете призначення Server Actions і те, як вони виконують серверну логіку без окремого API-ендпойнта.
Server Actions — це асинхронні функції, які виконуються на сервері, але можуть викликатися з інтерфейсу Next.js.
Вони зручні для операцій, які змінюють дані:
створення запису;
оновлення профілю;
видалення елемента;
оброблення даних HTML-форми;
виконання логіки, яка не повинна потрапляти в браузер.
Без Server Actions для такої операції часто створюють окремий API-ендпойнт, а потім викликають його з клієнта через fetch. Server Actions дають змогу передати серверну функцію безпосередньо у властивість action форми.
Server Action виконується на сервері, навіть якщо її викликають із браузера.
Щоб Next.js розпізнав функцію як Server Action, використовується директива "use server".
Найчастіше її розміщують на початку окремого файлу:
'use server'Усі експортовані функції з такого файлу можуть використовуватися як Server Actions.
Наприклад:
// app/actions.js
'use server'
export async function saveMessage(formData) {
const message = formData.get('message')
console.log('Повідомлення:', message)
}Директива "use server":
має бути рядком на початку файлу;
повідомляє Next.js, що функції виконуються на сервері;
не є імпортом або функцією;
не повинна замінюватися на 'use client'.
Server Action можна передати у властивість action HTML-форми:
<form action={saveMessage}>
<input name="message" />
<button type="submit">Зберегти</button>
</form>Після надсилання форми Next.js:
збере значення полів;
створить об'єкт FormData;
передасть його у Server Action;
виконає функцію на сервері.
Окремо викликати fetch і створювати API-маршрут для цього не потрібно.
Створімо просту сторінку з формою для збереження повідомлення.
// app/actions.js
'use server'
export async function saveMessage(formData) {
const message = formData.get('message')
if (typeof message !== 'string' || message.trim() === '') {
console.log('Повідомлення не може бути порожнім')
return
}
// Тут могла б бути операція запису в базу даних
console.log('Збережене повідомлення:', message.trim())
}// app/page.jsx
import { saveMessage } from './actions'
export default function HomePage() {
return (
<main>
<h1>Нове повідомлення</h1>
<form action={saveMessage}>
<label htmlFor="message">Повідомлення</label>
<input
id="message"
name="message"
type="text"
placeholder="Введіть текст"
/>
<button type="submit">Зберегти</button>
</form>
</main>
)
}Після натискання кнопки:
браузер надсилає форму;
Next.js викликає saveMessage;
значення поля доступне через formData.get('message');
console.log з'являється в терміналі, де запущено Next.js, а не в консолі браузера.
FormDataПоля форми повинні мати атрибут name. Саме за цим ім'ям Server Action отримує їхні значення.
<input name="email" type="email" />
<input name="age" type="number" />Отримати значення можна так:
export async function handleForm(formData) {
const email = formData.get('email')
const age = formData.get('age')
console.log(email)
console.log(age)
}formData.get() може повернути:
рядок;
об'єкт File для поля завантаження файлів;
null, якщо поля з таким ім'ям немає.
Тому дані потрібно перевіряти перед використанням.
При традиційному підході потрібно:
створити API-маршрут;
описати обробку HTTP-запиту;
викликати цей маршрут із компонента через fetch;
обробити відповідь.
Наприклад, клієнтський код мав би окремо надсилати запит:
await fetch('/api/messages', {
method: 'POST',
body: JSON.stringify({ message }),
})Server Action приховує цю технічну частину:
<form action={saveMessage}>
<input name="message" />
<button type="submit">Зберегти</button>
</form>Розробник зосереджується на функції, яка виконує операцію на сервері.
Server Actions особливо зручні, коли дія використовується лише всередині застосунку. Окремий API-ендпойнт може бути потрібен, якщо дані мають використовувати зовнішні клієнти або інші застосунки.
Server Action може містити серверну логіку, наприклад виклик функції для запису в базу даних:
// app/actions.js
'use server'
import { saveTaskToDatabase } from './database'
export async function createTask(formData) {
const title = formData.get('title')
if (typeof title !== 'string' || title.trim() === '') {
return
}
await saveTaskToDatabase({
title: title.trim(),
})
}Функція доступна формі, але код роботи з базою даних не відправляється до браузера.
У навчальному прикладі замість бази даних можна використовувати console.log, щоб побачити результат у терміналі.
Server Actions зазвичай оголошують через async:
'use server'
export async function createTask(formData) {
// Серверна логіка
}Це дає змогу використовувати await для роботи з базою даних або іншими асинхронними операціями.
Користувацькі дані не можна вважати правильними лише тому, що вони прийшли з HTML-форми.
export async function createTask(formData) {
const title = formData.get('title')
if (typeof title !== 'string' || title.trim().length < 3) {
return
}
// Подальша серверна логіка
}Перевірка повинна виконуватися на сервері, адже код браузера можна змінити або обійти.
Server Action — правильне місце для логіки, яка використовує:
облікові дані бази даних;
секретні ключі;
серверні змінні оточення;
приватні операції.
Однак це не означає, що Server Action автоматично дозволяє будь-яку операцію. Потрібно самостійно перевіряти вхідні дані та права користувача перед зміною даних.
nameУ цьому прикладі поле не буде доступне за ключем message:
<input type="text" />Правильний варіант:
<input name="message" type="text" />formData.messageFormData не працює як звичайний об'єкт. Для отримання значення потрібно використовувати get():
const message = formData.get('message')А не:
const message = formData.message"use client" замість "use server"Директива "use client" позначає клієнтський компонент і не перетворює функцію на Server Action.
Для окремого файлу з Server Actions використовуйте:
'use server'console.log у браузеріКод Server Action виконується на сервері, тому повідомлення з'являються в терміналі Next.js.
Користувач може надіслати порожнє, надто довге або некоректне значення. Server Action повинна перевіряти дані перед записом або іншою операцією.
Server Action — це асинхронна функція, яка виконується на сервері.
Для оголошення Server Actions використовується директива "use server".
Server Action можна передати у властивість action HTML-форми.
Дані форми надходять у функцію як об'єкт FormData.
Для цього сценарію не потрібно створювати окремий API-ендпойнт.
Серверний код і секрети не надсилаються до браузера.
Вхідні дані потрібно перевіряти всередині Server Action.