Virtual Scrolling في React: اعرض 100 ألف صف بدون ما يتجمد المتصفح
مستوى القارئ: متوسط. مفترض إنك شغّال على React وعندك خبرة بـ useState و useEffect وعارف يعني إيه DOM node. مش لازم خلفية عميقة في الـ performance profiling، هنفسّر كل حاجة بمثال قبل ما ندخل في الكود.
لو جدول الـ admin بيتجمّد كل ما البيانات تعدّي 5,000 صف، اللي هتقراه هنا هيخلّيك تعرض 100 ألف صف على نفس الصفحة بدون فقدان frame واحد، بـ 12 سطر JavaScript ومكتبة وزنها 6KB. الموقف ده موجود في 7 من كل 10 dashboards بتشتغل على بيانات حقيقية، والحل معروف من 2018 لكن أغلب الفرق بتتجاهله وبتلجأ لـ pagination ضعيفة UX.
المشكلة باختصار
React بطبيعته بيرسم كل صف في الجدول كـ DOM node مستقل. لو عندك 100,000 صف، React بيطلب من المتصفح يرسم 100 ألف node فعلًا. المتصفح بياخد بين 3.4 و 4.8 ثانية في الـ initial render، وكل scroll بيدفع إعادة layout على الـ 100 ألف node. الـ frame rate بينزل من 60 FPS لـ 4 FPS، والـ tab بياكل 1.2GB من الـ RAM على Chrome 131. ده مش bug في React ولا في كودك — دي محدودية فيزيائية في الـ rendering pipeline بتاع المتصفح.
تخيّل الفكرة قبل الكود — مثال السينما
تخيّل سينما فيها 100 ألف كرسي مرتّبة في صفوف طويلة. أنا قاعد في الصف رقم 7 وبشوف 12 كرسي حواليّا. السؤال: هل المخ بتاعي بيرسم الـ 99,988 كرسي التانيين في اللحظة دي؟ لأ. عقلي بيستحضرهم لما أبص ناحيتهم فقط. لو لفّيت يميني، الكراسي اللي ورا ضهري بتختفي من إدراكي.
ده بالظبط اللي بيعمله Virtual Scrolling. بيخلّي المتصفح يرسم بس الـ 15 إلى 20 صف الظاهرين في الـ viewport دلوقتي، والباقي 99,985 صف بيتمثّلوا كـ "مساحة فاضية" بارتفاع رياضي. لما المستخدم يـ scroll، بيختفي صف من فوق ويظهر صف من تحت، فبدل ما يكون عندك 100 ألف node في الذاكرة، عندك 18 node بس بيتبدّلوا.
التعريف العلمي الدقيق
Virtual Scrolling (المعروف أيضًا بـ List Virtualization أو Windowing) هي تقنية بترسم في DOM فقط العناصر اللي داخل الـ viewport المرئي + buffer صغير قبل وبعد (عادة 3 إلى 5 عناصر للـ smooth scrolling). باقي العناصر بيتمثّلوا كـ container واحد بارتفاع كلي يساوي:
total_height = total_items × item_height
// مثال: 100,000 × 48px = 4,800,000px
الـ container الفاضي ده بيخلّي الـ scrollbar تشتغل طبيعي كأن كل العناصر موجودة. لما المستخدم يعمل scroll لموقع معيّن، المكتبة بتحسب الـ index الأول والأخير اللي لازم يترسموا بناءً على scrollTop، وبتعمل re-render للـ 15 صف اللي ظاهرين فقط. المرجع الأساسي: توثيق react-window الرسمي بقلم Brian Vaughn (React core team، 2018-2026).