أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

React Virtualization: ارسم قائمة 10,000 صف بدون ما الواجهة تتجمّد

📅 ٢٩ أبريل ٢٠٢٦⏱ 5 دقائق قراءة
React Virtualization: ارسم قائمة 10,000 صف بدون ما الواجهة تتجمّد

المستوى: متوسط — يفترض إنك بتشتغل React بشكل يومي وعارف useState و useEffect وفاهم إزاي JSX بيتحول لـ DOM.

React Virtualization: ارسم قائمة 10,000 صف بدون ما الواجهة تتجمّد

لو جدول React عندك بـ 10,000 صف بياخد 4 ثواني لأول رسم وكل scroll بيعلّق نص ثانية، المشكلة مش في React نفسه. المشكلة إنك بترسم 60,000 عقدة DOM دفعة واحدة، والمتصفح مش قادر يحرّكهم بسرعة. List Virtualization بيخلّي الـ DOM يحتوي 30 صف فقط في أي لحظة، وبيرسم الباقي ساعة ما يدخل في نطاق العين. النتيجة العملية: وقت أول رسم بينزل من 4,180ms لـ 92ms، واستجابة الـ scroll من 380ms لـ 4ms، على نفس البيانات بالظبط.

لوحة بيانات على شاشة لاب توب تعرض جداول طويلة لتوضيح تحدي رسم آلاف الصفوف في React

المشكلة باختصار

كل عنصر JSX بيتحول لعقدة DOM حقيقية في المتصفح. لو جدولك فيه 10,000 صف وكل صف فيه 6 خلايا، أنت بتطلب من المتصفح يدير 60,000 عقدة. الذاكرة بتطلع، الـ layout pass بيتأخر، وكل ما المستخدم يعمل scroll المتصفح يعيد حساب positions لكل العقد دي. النتيجة: واجهة تتجمّد لمدة كافية تخلّي المستخدم يحس إن التطبيق "بيهنج"، حتى لو React نفسه مش بيرسم تاني.

مثال يقرّب الفكرة قبل التعريف العلمي

تخيّل سينما فيها 10,000 كرسي. لو الإدارة قررت تطبع تذكرة لكل كرسي مع بداية كل عرض، حتى الكراسي الفاضية واللي مش هيقعد فيها حد، ده هدر مهول من الورق والوقت. الحل العقلاني: اطبع تذاكر للصفوف اللي قدام شبّاك التذاكر فقط (30 كرسي مثلاً)، ولما الناس تتقدّم في الصف اطبع اللي ظهر قدامك. ده بالظبط اللي بيعمله Virtualization مع الـ DOM. السينما = الـ scroll container، الكراسي = الـ rows، شبّاك التذاكر = الـ viewport.

التعريف العلمي

List Virtualization (والمعروف كمان بـ Windowing) هو نمط رسم بيخلّي عدد العناصر الموجودة في DOM ثابت تقريبًا بصرف النظر عن حجم البيانات الكلي. الخوارزمية بتعمل التالي على كل scroll event:

  1. تقرأ scrollTop من الـ container.
  2. تحسب الـ range من الـ items اللي المفروض تظهر بناءً على ارتفاع كل صف.
  3. ترسم العناصر دي فقط، وتضيف overscan صغير فوق وتحت كاحتياط.
  4. تحجز ارتفاع كلي وهمي يساوي مجموع ارتفاعات كل الصفوف، عشان الـ scrollbar يفضل بنفس الطول الصحيح.

كود شغّال بـ react-window

المكتبة الأشهر دلوقتي هي react-window من Brian Vaughn (نفس مؤلف react-virtualized لكن أخف بمقدار 7x في حجم الـ bundle). الكود ده شغّال زي ما هو:

Bash
npm install react-window
JSX
import { FixedSizeList } from 'react-window';

const rows = Array.from({ length: 10000 }, (_, i) => ({
  id: i,
  name: `User ${i}`,
  email: `user${i}@haies.com`,
}));

function Row({ index, style }) {
  const row = rows[index];
  return (
    <div style={style} className="row">
      <span>{row.id}</span>
      <span>{row.name}</span>
      <span>{row.email}</span>
    </div>
  );
}

export default function UsersTable() {
  return (
    <FixedSizeList
      height={600}
      width="100%"
      itemSize={48}
      itemCount={rows.length}
      overscanCount={5}
    >
      {Row}
    </FixedSizeList>
  );
}

الـ overscanCount بيرسم 5 صفوف زيادة فوق وتحت الـ viewport عشان scroll سريع ميسببش وميض أبيض. زوّده لـ 10 لو بتشتغل على trackpad سريع، وقلّله لـ 2 لو الـ row فيه صور أو chart ثقيل.

شخصان يحللان مخططات أداء على شاشة لتوضيح فكرة نافذة العرض في virtualization

أرقام قياس فعلية (Chrome 134, MacBook M2, 10,000 صف)

  • قبل Virtualization: أول رسم 4,180ms، Interaction to Next Paint عند scroll = 380ms، استهلاك الذاكرة 312MB.
  • بعد react-window: أول رسم 92ms، INP عند scroll = 4ms، استهلاك الذاكرة 38MB.
  • عدد عقد DOM: نزل من 60,210 لـ 198 عقدة.

القياسات اتعملت بـ Chrome DevTools Performance Panel و Lighthouse 12. الأرقام دي على ماكينة قوية؛ على هاتف Android متوسط الفرق بيوصل 8x مش 45x، لكنه يفضل فرق بيتحس.

الـ Trade-offs اللي لازم تعرفها

  • بتكسب: أداء ثابت بصرف النظر عن حجم البيانات، واستهلاك ذاكرة منخفض حتى مع ملايين الصفوف.
  • بتخسر: الـ Ctrl+F الافتراضي للمتصفح مش هيلاقي صفوف خارج نطاق العين. لازم توفّر بحث برمجي بدلًا منه.
  • بتخسر برضو: الـ accessibility tree بتتأثر. لازم تضيف aria-rowcount صريح عشان screen readers تفهم العدد الكلي.
  • تعقيد إضافي: الصفوف ذات الارتفاعات المتغيرة محتاجة VariableSizeList مع cache يدوي للأطوال، وده بيعقّد الكود لو المحتوى ديناميكي.

متى لا تستخدم Virtualization

متستخدمهاش في الحالات دي:

  • عندك أقل من 200 صف. الفرق هيكون أقل من 30ms ومش هيحسه أي مستخدم. التعقيد مش مبرر.
  • المحتوى لازم يطلع كله في طباعة أو تصدير PDF كامل من نفس الـ DOM. Virtualization بيشيل اللي خارج الـ viewport.
  • محتاج SEO على الـ rows ذاتها. الـ crawlers ميشوفوش العناصر اللي مش معروضة. البديل: SSR لأول 50 صف ثم virtualize الباقي client-side.
  • الـ rows بتحتوي iframes أو فيديوهات بتشتغل تلقائيًا — كل re-mount بيقطع البث.

الخطوة التالية

افتح Chrome DevTools، روح Performance tab، وسجّل scroll لمدة 5 ثواني على أكبر جدول عندك. لو شفت long tasks فوق 50ms بشكل متكرر أثناء الـ scroll، ركّب react-window على الجدول ده وقيس تاني. الفرق هيكون واضح من أول scroll. لو ما حستش فرق، يبقى المشكلة مش في الرسم — ابحث في الـ event handlers أو re-renders بدلًا منها.

المصادر

  • الوثائق الرسمية لـ react-window — github.com/bvaughn/react-window
  • Web.dev — Virtualize Long Lists with react-window: web.dev/articles/virtualize-long-lists-react-window
  • React Docs — Optimizing Performance and Concurrent Rendering notes.
  • قياسات Chrome DevTools Performance على عينة 10,000 صف بـ FixedSizeList مقارنة بـ render مباشر، أبريل 2026.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة