استكشف مكوّنات الخادم، وقراءة الوعود بواسطة use، والتحديثات التفاؤلية في React 19.
افتح هذا الدرس في KodokonReact Server Components (RSC) تعيد رسم الحدّ بين العميل والخادم. مكوّن الخادم يُشغَّل على الخادم فقط: شيفرته لا تصل أبداً إلى حزمة العميل، ويمكن أن يكون async، ويقرأ قاعدة البيانات أو نظام الملفات مباشرةً، ويُرسَل ناتجه إلى المتصفّح كـ دفق مُسلسَل (حمولة RSC) يدمجه React مع شجرة العميل. في المقابل، لا يملك حالة، ولا تأثيرات، ولا وصولاً إلى المتصفّح: لا useState، ولا useEffect، ولا معالِجات أحداث. وهو لا يُعاد عرضه أبداً على العميل.
// Server component: never sent to the client.
export default async function NotesPage() {
const notes = await db.notes.findAll();
return (
<ul>
{notes.map((note) => (
<li key={note.id}>{note.title}</li>
))}
</ul>
);
}تعيش التفاعلية في مكوّنات العميل، المميَّزة بموجِّه 'use client' في أعلى الملف. هذا الموجِّه لا يميّز "مكوّن عميل" بل حدّاً: كل ما تستورده تلك الوحدة ينتقل أيضاً إلى جانب العميل. الخصائص التي تعبر الحدّ يجب أن تكون قابلة للتسلسل: كائنات عادية، مصفوفات، وعود... لكن أبداً دوال عادية أو نُسَخ من أصناف.
'use client';
import { useState } from 'react';
export function LikeButton({ initialCount }) {
const [count, setCount] = useState(initialCount);
return (
<button onClick={() => setCount(count + 1)}>
{count} likes
</button>
);
}يُدخِل React 19 الواجهة use، التي تقرأ قيمة وعد أو سياق. على خلاف الخطّافات، يمكن استدعاء use داخل شرط أو حلقة. بالنظر إلى وعد، يُعلّق المكوّن حتى الحلّ، معتمداً على أقرب حدّ Suspense. النمط الاصطلاحي: مكوّن خادم يُنشئ الوعد من دون انتظاره، ويمرّره كخاصية، ومكوّن عميل يستهلكه بواسطة use: يبدأ الخادم بدفق الصفحة من دون انتظار البيانات.
import { use, Suspense } from 'react';
function Comments({ commentsPromise }) {
const comments = use(commentsPromise);
return comments.map((c) => (
<p key={c.id}>{c.text}</p>
));
}
function Page({ commentsPromise }) {
return (
<Suspense fallback={<Spinner />}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
);
}على جانب التفاعل، يُعلِّم useTransition التحديث بأنه غير ملحّ ويكشف isPending كي تعرض مؤشّراً خفيفاً من دون حجب الإدخال. ويُكمِل useOptimistic الثنائي في تحويرات الشبكة: تعرض فوراً الحالة المأمولة بينما يجري إجراء غير متزامن؛ وعند انتهاء الإجراء (نجاحاً أو فشلاً)، يُسقِط React القيمة التفاؤلية ويعرض من جديد الحالة الحقيقية، تلك التي تأتي من مصدر الحقيقة.
const [optimisticLikes, addOptimisticLike] =
useOptimistic(likes, (count, delta) => count + delta);
function handleLike() {
startTransition(async () => {
addOptimisticLike(1);
await saveLike();
// At the end, React shows the real state again.
});
}use بخرقها؟useOptimistic حين ينتهي الإجراء غير المتزامن؟