'use server' - This feature is available in the latest Canary

Canary

'use server' רק אם אתם משתמשים ב-React רכיבי שרת או בונים ספרייה שתואמת.

'use server' מסמן פונקציות בצד השרת אפשר לקרוא להן מקוד בצד הלקוח.


עיון ב-API

'use server'

הוסיפו 'use server' התחיל גוף של פונקציה אסינכרונית כדי לסמן אותה כפונקציה שהלקוח יכול לקרוא לה. לפונקציות האלו אנחנו קוראים פעולות שרת.

async function addToCart(data) {
'use server';
// ...
}

כשקוראים ל-Server Action מהלקוח, בקשת רשת לשרת שכוללת עותק מסודר (בסדרה) של כל הארגומנטים שעברו. אם ה-Server Action מחזיר ערך, הערך הזה יעבור בסידרה ויוחזר ללקוח.

במקום לסמן כל פונקציה בנפרד עם 'use server', אפשר להוסיף את ההנחיה בראש קובץ כדי לסמן שכל ה-exports בקובץ הם פעולות שרת שאפשר להשתמש בהם בכל מקום, כולל ייבוא ​​מתוך קוד לקוח.

הבהרות

  • __TK_0 חייב להופיע ממש בתחילת הפונקציה או המודול, לפני כל קוד אחר כולל ייבוא (מותרות הערות מעל ההנחיה). יש לכתוב אותו במרכאות יחידות או כפולות, לא עם תקלות.
  • אפשר להשתמש ב-'use server' רק בקבצים שרצים בצד השרת. את ה-Server Actions אפשר להעביר ל-Client Components דרך props. ראו סוג נתמכים ל-serialization.
  • כדי לייבא פעולת שרת מתוך קוד לקוח, ההנחיה חייבת להיות ברמת מודול.
  • מה שקשור הרשת מתחת למכסה המנוע הן תמיד אסינכרוניות, אפשר להשתמש ב-'use server' רק על פונקציות אסינכרון. *כתובו תמיד לארגומנטים של פעולות שרת כקלט לא מהימן ובצעו הרשאה לכל שינוי מצב. ראו שיקולי אבטחה.
  • מומלץ לקרוא ל-Server Actions בתוך transition. פעולות שרת שמועברות ל-<form action> או ל-formAction ירוצו אוטומטית בתוך המעבר.
  • פעולות שרת מיועדות למוטציות שמעדכנות מצב בצד השרת; הם לא מומלצים לשליפת נתונים. בהתאם לכך, מסגרות שמממשים פעולות שרת מעבדים פועלים אחת בכל פעם ואין להם דרך למטמן את ערך החזרה.

שיקולי אבטחה

הארגוים ל-Server Actions נשלטים לגמרי על ידי הלקוח. מטעמי אבטחה, רק שאל את זה תמיד כקלט לא מהימן, ודאו שאתה מאמתים ומבצעים escaping לארגומנטים לפי הצורך.

בכל פעולת שרת, ודאו שהמשתמש המחובר מורשה לבצע את הפעולה.

Under Construction

כדי למנוע שליחה של רגישות מתוך פעולת שרת, קיים מידע APIs ניסיוניים מסוג גוון שמונעים העברת ערכים ייחודיים ואובייקטים לקוד לקוח.

ראו experimental_taintUniqueValue ו-experimental_taintObjectReference.

ארגומנטים וערכי החזרה שניתנים ל-serialization

מה שקוד לקוח קורא ל-Server Action דרך הרשת, כל הארגומנטים שמועברים חייבים להיות ניתנים ל-Serialization.

אלה הסוגים הנתמכים לארגומנטים של פעולת שרת:

לעומת זאת, אלה אינם נתמכים:

  • אלמנטים React או JSX
  • פונקציות, כולל פונקציות קומפונטה או כל פונקציה אחרת שאינה Server Action
  • שיעורים
  • אובייקטים שהם מופעים של כל class (מלבד ה-built-ins שהוא זכרו) או אובייקטים עם null prototype
  • סמלים שלא נרשמו גלובלית, למשל: Symbol('my new symbol')

ערכי חזרה נתמכים ב-serialization זהים ל-ניתן להמשכה props עבור רכיב לקוח בגבול.

שימוש

פעולות שרת בתוך טפסים

מקרה הפעלה הנפוץ ביותר ל-Server Actions הוא קריאה לפונקציות שרת שמבצעות מוטציה בנתונים. בדפדפן, אלמנט HTML form הוא הדרך המסורתית לשלוח מוטציה מצד המשתמש. עם React Server Components, React מוסיף תמיכה הסבר ראשונה ב-Server Actions בתוך forms.

הנה טופס שמאפשר למשתמש לבקש שם משתמש.

// 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. כשקוראים ל-Server Action מתוך טופס, React יעביר את FormData של הטופס כארגומנט ראשון ל-Server Action.

על העברת שרת פעולה ל-action של הטופס, React יכול לבצע שיפור פרוגרסיבי לטופס. אנו יכולים לשלוח טפסים גם לפני שחבילת JavaScript נאמר.

טיפול בערכי חזרה בטפסים

בטופס בקשת שם משתמש יכול שהשם לא זמין. requestUsername צריך להחזיר לנו אם לפעול או נכשלה.

כדי לעדכן את ה-UI לפי תוצאת פעולת שרת תוך תמיכה ב-progressive enhancement, השתמשו ב-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>
</>
);
}

שימו לב שכמו רוב ה-Hooks, useFormState יכול להיקרא רק מתוך קוד לקוח.

קריאה ל-Server Action מחוץ ל-<form>

פעולות שרת הן נקודות הקצה בשרת, ואפשר לקרוא אותם מכל מקום בקוד לקוח.

כשמשתמשים ב-Server Action מחוץ ל-form, קראו לו בתוך transition, כדי לאפשר להציג אינדיקציית טעינה, להראות עדכוני state אופטימיים, ולטפל. טפסים עוטפים פעולות שרת אוטומטית בתוך מעברים.

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;
}

כדי לקרוא את הערך החזרה של פעולת שרת צריך לבצע await להבטחת שמוחזר.