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

Canary

هذه التوجيهات لازمة فقط إذا كنت تستخدم RSC (مكونات الخادم) أو تبني مكتبة متوافقة معها.

'use server' يميّز دوال الخادم (server-side functions) التي يمكن استدعاؤها في الكود من جانب العميل (client-side).


المرجع

'use server'

أضف 'use server'; في أعلى دالة غير متزامنة (async) لتمييز أن الدالة يمكن تنفيذها من قبل العميل. نسمي هذه الدوال Server Actions.

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

يمكن تمرير هذه الدالة إلى العميل، عندما تُستدعى، ستنفذ طلب شبكة إلى الخادم يتضمن نسخة متسلسلة من أي معاملات تم تمريرها. إذا كان Server Action ترجع قيمة، سيتم تسلسلها وإرجاعها إلى العميل.

بدلا من وضع 'use server' في أول الدالة، يمكنك إضافة 'use server'; في أعلى ملف لتمييز كل التصديرات في هذا الملف كدوال خادم غير متزامنة يمكن استخدامها في أي مكان، بما في ذلك استيرادها في ملفات مكونات العميل.

ملاحظات

  • يجب أن تكون 'use server' في بداية الدالة أو الملف. فوق أي كود آخر، بما في ذلك الاستيرادات (التعليقات قبل 'use server' مسموح به) يجب كتابتها بعلامة تنصيص مفردة أو مزدوجة. ليس backticks.
  • يمكن استخدام 'use server' في ملفات الخادم فقط، ومن ثَمّ يمكن تمرير Server Actions إلى مكونات العميل من خلال الخصائص (props). اقرأ أيضًا أنواع التسلسل.
  • عند استيراد Server Action من كود Client، يجب استخدام التوجيهات على مستوى الملف وليس الدالة.
  • لأن الاستدعاءات الشبكية الأساسية دائمًا غير متزامنة، يمكن استخدام 'use server' فقط في دوال غير متزامنة (async).
  • تذكر أن المعاملات الممررة إلى دالة مميزة بـ 'use server' متحكم بها بالكامل من جانب العميل. للأمان، عاملها دائمًا كإدخال غير موثوق به، وتأكد من التحقق من صحتها وتصفيتها كما يناسبك.
  • يفضل استعمال Server Actions في useTranistion، أما Server Actions التي يتم تمريرها إلى <form action> أو formAction سيتم إضافة transition لهم تلقائيًا.
  • تم تصميم Server Actions لعمليات تعديل حالة الخادم. لا ينصح باستخدامهم في جلب البيانات، ووفقًا لذلك، فإن الإطارات التي تنفذ Server Actions عادة تعالج إجراء واحد في كل مرة وليس لديها طريقة لتخزين قيمة الإرجاع.

الاعتبارات الأمنية

تُحكم الوسائط المُرسَلة إلى Server Actions بالكامل من قبل العميل. من أجل الأمان، دائمًا عاملها كمُدخَلات غير موثوق بها، وتأكد دائمًا من التحقق وتهيئة الوسائط بالطريقة المناسبة.

في أي Server Action، تأكد من التحقق من أن المستخدم الذي سجل دخوله مسموح له بأداء تلك العملية.

Under Construction

لمنع إرسال بيانات حساسة من إجراء خادمي، هناك واجهات برمجة تجريبية لمنع تمرير القيم والكائنات الفريدة إلى كود العميل.

اطلع على experimental_taintUniqueValue و experimental_taintObjectReference.

وسائط وقيم الإرجاع قابلة للتسلسل

عندما يستدعي كود العميل Server Action عبر الشبكة، فإن أي وسائط يتم تمريرها ستحتاج إلى أن تكون قابلة للتسلسل.

فيما يلي الأنواع المدعومة لوسائط إجراء الخادم:

وتجدر الإشارة إلى عدم دعم ما يلي:

  • عناصر React، أو JSX
  • الدوال بما في ذلك المكونات أو أي دوال ليست Server Action
  • Classes
  • كائنات تكون مثيلات من أي Class (بخلاف المدمجة المذكورة) أو كائنات ب null prototype
  • الرموز التي لم تُسجل عالمياً، مثل Symbol('my new symbol')

قيم الإرجاع القابلة للتسلسل المدعومة هي نفسها كالخصائص القابلة للتسلسل لـ Boundry Client Component.

الاستخدام

Server Actions في النماذج <form>

إن أشهر استخدام للـ Server Actions سيكون مناداة هذه الدوال لتحديث البيانات. في المتصفح، يعتبر عنصر HTML <from> الطريقة التقليدية للمستخدم لإرسال تعديل. مع React Server Components، تقدم React دعمًا متكاملاً للـ Server Actions في النماذج..

هذا النموذج يطلب من المستخدم ادخال اسمه:

// 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 كـ Server Action إلى <form>. عندما يقوم المستخدم بإرسال هذا النموذج، يتم إرسال طلب شبكة إلى دالة الخادم requestUsername. عند استدعاء Server Action في نموذج، ستقوم React بتزويد FormData النموذج كالوسيط الأول للـ Server Action.

من خلال تمرير Server Action إلى action، يمكن لـ React تحسين النموذج تدريجيًا. وهذا يعني أنه يمكن إرسال النماذج قبل تحميل ملف JavaScript.

معالجة القيم الراجعة من النماذج

في نموذج اسم المستخدم السابق، من المحتمل ألا يوجد username. في هذه الحالة يجب على requrestUsername أن يخبرنا إن كان فشل أم لا.

لتحديث واجهة المستخدم اعتماد على نتيجة Server Action يمكنك استخدام useActionState.

// 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 { useActionState } from 'react';
import requestUsername from './requestUsername';

function UsernameForm() {
const [state, action] = useActionState(requestUsername, null, 'n/a');

return (
<>
<form action={action}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
<p>Last submission request returned: {state}</p>
</>
);
}

لاحظ أن useActionState يمكن استخدامها فقط في client code.

استخدام Server Action خارج <form>

تعتبر Server Actions نقاط نهاية خادم (Endpoint) ويمكن استدعاؤها في أي مكان في كود العميل.

عند استخدام Server Action خارج <form>، استدعها في Transition، والذي يسمح لك بعرض مؤشر التحميل، وعرض تحديثات الحالة التفاؤلية، والتعامل مع الأخطاء غير المتوقعة. ستقوم النماذج تلقائيًا بتغليف Server Actions في Transition.

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 الـ Promise المرجعة.