'use server'
'use server'
потрібен лише якщо ви використовуєте компоненти сервера React або створюєте сумісну з ними бібліотеку.
'use server'
позначає функції на стороні сервера, які можна викликати з клієнтського коду.
Довідник
'use server'
Додайте 'use server'
у верхній частині тіла асинхронної функції, щоб позначити функцію як таку, що викликається клієнтом. Ми називаємо ці функції Дії сервера.
async function addToCart(data) {
'use server';
// ...
}
При виклику дії сервера на клієнтській стороні, він зробить мережевий запит до сервера, який містить серіалізовану копію всіх переданих аргументів. Якщо серверна дія поверне значення, це значення буде серіалізовано і повернуто клієнту.
Замість індивідуального позначення функцій за допомогою 'use server'
, ви можете додати директиву до початку файлу, щоб позначити всі експортовані дані у цьому файлі як дії сервера, які можна використовувати будь-де, зокрема імпортувати у клієнтський код.
Застереження
'use server'
повинні бути на самому початку функції або модуля; над будь-яким іншим кодом, включаючи імпорт (коментарі над директивами є допустимими). Вони повинні бути написані з одинарними або подвійними лапками, без зворотних лапок.'use server'
можна використовувати лише у файлах на стороні сервера. Результуючі дії сервера можуть бути передані клієнтським компонентам через пропси. Дивіться підтримувані типи для серіалізації.- Щоб імпортувати серверну дію з клієнтського коду, директиву слід використовувати на рівні модуля.
- Оскільки базові мережеві виклики завжди асинхронні,
'use server'
можна використовувати лише для асинхронних функцій. - Завжди розглядайте аргументи серверних дій як ненадійні вхідні дані і дозволяйте будь-які мутації. Дивіться міркування щодо безпеки.
- Дії сервера слід викликати у переході. Дії сервера, передані в
<form action>
абоformAction
, будуть автоматично викликані в переході. - Серверні дії призначено для мутацій, які оновлюють стан на стороні сервера; їх не рекомендовано використовувати для отримання даних. Відповідно, фреймворки, що реалізують серверні дії, зазвичай обробляють по одній дії за раз і не мають можливості кешувати значення, що повертається.
Міркування безпеки
Аргументи до дій сервера повністю контролюються клієнтом. Задля безпеки, завжди розглядайте їх як ненадійні вхідні дані і переконайтеся, що аргументи перевірено та екрановано належним чином.
У будь-якій дії сервера переконайтеся, що користувачеві, який увійшов, дозволено виконувати цю дію.
Щоб запобігти надсиланню конфіденційних даних з серверної дії, існують експериментальні API для запобігання передачі унікальних значень та об'єктів до клієнтського коду.
Дивіться experimental_taintUniqueValue та experimental_taintObjectReference.
Аргументи та значення, які можна серіалізувати
Оскільки клієнтський код викликає серверну дію через мережу, будь-які передані аргументи мають бути серіалізованими.
Підтримувані типи для аргументів дії сервера:
- Примітиви
- Змінні, що містять серіалізовані значення
- Дата
- FormData instances
- Прості об'єкти: створені за допомогою ініціалізаторів об'єктів, з серіалізованими властивостями
- Функції, які є діями сервера
- Обіцянки
Зокрема, не підтримуються:
- React-елементи, або JSX
- Функції, включно з функціями компонентів або будь-якими іншими функціями, які не є діями сервера
- Класи
- Об'єкти, які є екземплярами будь-якого класу (крім згаданих вбудованих) або об'єкти з нульовим прототипом
- Символи, не зареєстровані глобально, наприклад,
Symbol('my new symbol')
Підтримувані серіалізовані значення повернення такі самі, як і серіалізовані пропси для граничного клієнтського компонента.
Використання
Дії сервера у формах
Найпоширенішим випадком використання серверних дій буде виклик серверних функцій, які змінюють дані. У браузері елемент HTML-форми є традиційним підходом для користувача, щоб відправити мутацію. З Компонентами сервера React впроваджується першокласна підтримка серверних дій у формах.
Ось форма, яка дозволяє користувачеві запитувати ім'я користувача.
// App.js
async function requestUsername(formData) {
'use server';
const username = formData.get('username');
// ...
}
export default function App() {
return (
<form action={requestUsername}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
);
}
У цьому прикладі requestUsername
є дією сервера, переданою до <form>
. Коли користувач відправляє цю форму, відбувається мережевий запит до серверної функції requestUsername
. При виклику серверної дії у формі React передасть дані форми
Обробка значень, що повертаються у формах
У формі запиту імені користувача може існувати ймовірність того, що ім'я користувача недоступне. requestUsername
має повідомити нам, чи це не так.
Щоб оновити інтерфейс на основі результату дії сервера з підтримкою поступового покращення, використовуйте useFormState
.
// requestUsername.js
'use server';
export default async function requestUsername(formData) {
const username = formData.get('username');
if (canRequest(username)) {
// ...
return 'successful';
}
return 'failed';
}
// UsernameForm.js
'use client';
import { useFormState } from 'react-dom';
import requestUsername from './requestUsername';
function UsernameForm() {
const [returnValue, action] = useFormState(requestUsername, 'n/a');
return (
<>
<form action={action}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
<p>Last submission request returned: {returnValue}</p>
</>
);
}
Зверніть увагу, що як і більшість хуків, Серверні дії є відкритими кінцевими точками сервера і можуть бути викликані будь-де у клієнтському коді. При використанні серверної дії поза формою, викликайте серверну дію у переході, що дозволяє відображати індикатор завантаження, показувати оптимістичні оновлення стану та обробляти неочікувані помилки. Форми автоматично обгортатимуть дії сервера у переходи. Щоб прочитати значення повернення дії сервера, вам потрібно useFormState
можна викликати лише в import incrementLike from './actions';
import { useState, useTransition } from 'react';
function LikeButton() {
const [isPending, startTransition] = useTransition();
const [likeCount, setLikeCount] = useState(0);
const onClick = () => {
startTransition(async () => {
const currentCount = await incrementLike();
setLikeCount(currentCount);
});
};
return (
<>
<p>Total Likes: {likeCount}</p>
<button onClick={onClick} disabled={isPending}>Like</button>;
</>
);
}
// actions.js
'use server';
let likeCount = 0;
export default async function incrementLike() {
likeCount++;
return likeCount;
}
дочекатися
повернення обіцянки.