React والأطر البرمجية الحديثة للواجهات الأمامية
مكونات الخادم وبنية Next.js
تمثل مكونات خادم React (RSC) أكبر تحول معماري في React منذ الخطافات. فهم هذا النموذج يُختبر بشكل متزايد في المقابلات، خاصة في الشركات التي تستخدم Next.js.
النموذج الذهني لمكونات الخادم
لدى React الآن نوعان من المكونات:
| مكونات الخادم | مكونات العميل | |
|---|---|---|
| أين تعمل | الخادم فقط | الخادم (SSR) + العميل (الترطيب) |
| يمكنها استخدام | async/await، قاعدة البيانات، fs | useState, useEffect, معالجات الأحداث |
| لا يمكنها استخدام | الخطافات، واجهات المتصفح، معالجات الأحداث | الوصول المباشر لقاعدة البيانات، fs |
| تأثير الحزمة | صفر — الكود يبقى على الخادم | مُضمّن في حزمة JS |
| الافتراضي في App Router | نعم (افتراضي) | يجب إضافة "use client" |
// مكون الخادم (افتراضي في App Router) — لا حاجة لتوجيه
async function ProductPage({ params }) {
// هذا الكود يعمل فقط على الخادم
const product = await db.products.findById(params.id);
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
{/* مكون عميل للأجزاء التفاعلية */}
<AddToCartButton productId={product.id} price={product.price} />
</div>
);
}
// مكون العميل — يجب أن يحتوي على توجيه "use client"
'use client';
import { useState } from 'react';
function AddToCartButton({ productId, price }) {
const [added, setAdded] = useState(false);
return (
<button onClick={() => {
addToCart(productId);
setAdded(true);
}}>
{added ? 'تمت الإضافة!' : `أضف للسلة — $${price}`}
</button>
);
}
متى تستخدم كلاً منهما
أبقِ كمكون خادم عندما:
- جلب البيانات من قاعدة بيانات أو API
- الوصول لموارد الخلفية (نظام الملفات، متغيرات البيئة)
- عرض محتوى ثابت أو نادر التحديث
- المكون ليس لديه تفاعلية
حوّل لمكون عميل عندما:
- استخدام خطافات React (useState, useEffect, useRef, إلخ)
- إضافة معالجات أحداث (onClick, onChange, onSubmit)
- استخدام واجهات المتصفح فقط (localStorage, window, navigator)
- المكون يحتاج للاستجابة لتفاعل المستخدم
أفضل ممارسة: ادفع حدود "use client" لأسفل الشجرة قدر الإمكان. أبقِ تخطيطات الأب كمكونات خادم واجعل فقط المكونات الورقية التفاعلية على جانب العميل.
أنماط Next.js App Router
جلب البيانات
// مكون الخادم: الجلب مباشرة (لا حاجة لـ useEffect)
async function BlogPosts() {
const posts = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 } // ISR: إعادة التحقق كل ساعة
}).then(r => r.json());
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
إجراءات الخادم
// إجراء الخادم: مُعرّف بـ "use server"
async function createPost(formData) {
'use server';
const title = formData.get('title');
const content = formData.get('content');
await db.posts.create({ title, content });
revalidatePath('/posts');
}
// يُستخدم في نموذج (مكون خادم)
function NewPostForm() {
return (
<form action={createPost}>
<input name="title" required />
<textarea name="content" required />
<button type="submit">إنشاء منشور</button>
</form>
);
}
بث SSR
import { Suspense } from 'react';
// الهيكل يُعرض فورًا، الأجزاء البطيئة تُبث تدريجيًا
async function Dashboard() {
return (
<div>
<h1>لوحة التحكم</h1>
{/* تُعرض فورًا */}
<Suspense fallback={<Skeleton />}>
{/* تُبث عند جاهزية البيانات */}
<RevenueChart />
</Suspense>
<Suspense fallback={<Skeleton />}>
<RecentOrders />
</Suspense>
</div>
);
}
استراتيجيات العرض
| الاستراتيجية | متى يتحدث المحتوى | حالة الاستخدام |
|---|---|---|
| SSG (ثابت) | وقت البناء فقط | صفحات التسويق، التوثيق |
| ISR (تدريجي) | دوريًا (مؤقت إعادة التحقق) | منشورات المدونة، صفحات المنتجات |
| SSR (ديناميكي) | كل طلب | محتوى مخصص، بيانات فورية |
| جانب العميل | بعد الترطيب | ميزات تفاعلية للغاية |
// SSG: بدون خيارات fetch (افتراضي)
const data = await fetch('https://api.example.com/static');
// ISR: إعادة التحقق كل 60 ثانية
const data = await fetch('https://api.example.com/posts', {
next: { revalidate: 60 }
});
// SSR: طازج في كل طلب
const data = await fetch('https://api.example.com/dashboard', {
cache: 'no-store'
});
أسئلة المقابلات الشائعة
س: "هل يمكن لمكون الخادم استيراد مكون عميل؟"
نعم. يمكن لمكونات الخادم عرض مكونات العميل كأبناء. يحتاج مكون العميل فقط لتوجيه "use client".
س: "هل يمكن لمكون العميل استيراد مكون خادم؟"
ليس مباشرة. لكن يمكن لمكون العميل قبول مكونات الخادم كأبناء عبر نمط خاصية children.
س: "ماذا يحدث لكود مكون الخادم في المتصفح؟" لا شيء — لا يصل أبدًا للمتصفح. كود مكون الخادم غير مُضمّن في حزمة JavaScript. هذه هي فائدة الأداء الرئيسية.
نصيحة للمقابلات: القدرة على شرح حدود RSC — لماذا يعمل كود معين على الخادم مقابل العميل، وكيف تتدفق البيانات بينهما — هي عامل تمييز. معظم المرشحين يمكنهم استخدام الخطافات لكن قليلون يستطيعون توضيح النموذج المعماري.
الآن لنطبق ما تعلمته ببناء جدول بيانات قابل للبحث في المختبر التالي. :::