0Pricing
React Academy · درس

قياس عناصر DOM باستخدام useLayoutEffect

اقرأ أبعاد العناصر ومواضعها وإزاحات التمرير بعد التخطيط وقبل الرسم لتجنّب الوميض

قياس عناصر DOM باستخدام useLayoutEffect درس مجاني في React Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في React Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة React Academy 4 دروس في المجموع.

نظرة عامة على getBoundingClientRect

تعيد element.getBoundingClientRect() كائنًا من النوع DOMRect يحتوي على حجم العنصر وموضعه بالنسبة إلى إطار العرض: top وright وbottom وleft وwidth وheight. وتجبر المتصفح على إجراء حساب للتخطيط لإعادة قيم دقيقة، لذا ينبغي استدعاؤها باعتدال.

مشكلة القراءة في useEffect

إذا قرأت getBoundingClientRect() داخل useEffect، فسيكون المتصفح قد أجرى الرسم بالفعل. وإذا عيّنت الحالة بعد ذلك استنادًا إلى القياس، فسيعيد React التصيير وسيجري المتصفح الرسم مرة أخرى. وقد يرى المستخدم العنصر لفترة وجيزة في موضعه أو حجمه غير الصحيح قبل ظهور التصحيح في الرسم الثاني.

لماذا يحل useLayoutEffect هذه المشكلة

تحدث قراءة القياسات في useLayoutEffect بعد تعديلات DOM وقبل الرسم. ويؤدي أي تحديث للحالة ناتج عن القياس إلى إعادة تصيير React بشكل متزامن واعتماد DOM المصحح، وكل ذلك قبل أن يرسم المتصفح أي شيء. ولا يرى المستخدم سوى النتيجة النهائية الصحيحة ضمن دورة رسم واحدة.

تحديد موضع التلميح

يحتاج التلميح إلى الظهور بالقرب من العنصر الذي يشغّله. قِس موضع العنصر المشغّل في useLayoutEffect باستخدام getBoundingClientRect()، واحسب الموضع المطلق للتلميح، ثم عيّن هذا الموضع في الحالة. وهكذا يُصيَّر التلميح في المكان الصحيح منذ أول رسم، من دون قفزة مرئية من موضع أولي غير صحيح.

تحريك العنصر: قراءة الحجم الأولي

لتحريك عنصر من حجمه الطبيعي غير المقيّد إلى حجم ثابت، تحتاج إلى معرفة الحجم الطبيعي قبل تطبيق القيد. اقرأ ارتفاع العنصر في useLayoutEffect قبل تطبيق أي نمط للتحريك، وخزّنه في الحالة، ثم استخدمه كقيمة إطار البداية في انتقال CSS.

ارتفاع الرأس الثابت

عندما تحتوي الصفحة على رأس ثابت، يحتاج محتوى الصفحة إلى حشوة علوية تساوي ارتفاع الرأس حتى لا يختفي خلفه. قِس ارتفاع الرأس في useLayoutEffect باستخدام ref: headerRef.current.getBoundingClientRect().height. عيّن هذه القيمة للخاصية paddingTop في حاوية المحتوى. وبذلك يكون التخطيط صحيحًا منذ أول تصيير.

يؤدي تحديث الحالة إلى إعادة تصيير متزامنة

عندما تستدعي setState داخل useLayoutEffect، ينفّذ React فورًا دورة تصيير واعتماد أخرى ضمن الكتلة المتزامنة نفسها. وتنفّذ إعادة التصيير هذه أيضًا useLayoutEffect الخاص بها. احرص على عدم إنشاء حلقة لا نهائية: لا تحدّث الحالة إلا إذا اختلف القياس الجديد عن قيمة الحالة الحالية.

SSR: تعيد القياسات صفرًا

لا توجد عناصر DOM على الخادم، لذا قد يتسبب getBoundingClientRect() في خطأ أو يعيد أصفارًا. احمِ useLayoutEffect باستخدام فحص: if (typeof window === 'undefined') return;. وقد تحتاج تطبيقات SSR إلى إجراء hydration باستخدام حجم نائب، ثم القياس بعد hydration على العميل.

استخدام ResizeObserver للتتبع المستمر

يوفر القياس لمرة واحدة باستخدام useLayoutEffect الحجم وقت التركيب. أما لتتبع تغيّرات الحجم أثناء تغيير حجم العنصر، بسبب تغيير حجم النافذة أو المحتوى الديناميكي أو تغيّرات CSS، فاستخدم ResizeObserver بدلًا منه. إذ يستدعي دالة رد اتصال كلما تغيّر حجم العنصر، مما يجعله أنسب للمكوّنات المتجاوبة.

تجنب القياسات الزائدة

إذا احتاجت تأثيرات متعددة إلى القياس نفسه، فاحسبه مرة واحدة وشاركه عبر context أو مرّره إلى الأسفل باعتباره props. يؤدي حساب قيمة getBoundingClientRect() نفسها في عدة استدعاءات لـ useLayoutEffect إلى إجراء قراءات تخطيط متزامنة متعددة، وكل قراءة منها مكلفة نسبيًا. لذلك ينبغي توحيد القياسات كلما أمكن.

توقيت ref مع useLayoutEffect

تُملأ Refs قبل تشغيل التأثيرات. وعند تنفيذ useLayoutEffect، يُضمن أن يشير ref.current إلى عنصر DOM. ولهذا ينجح هذا النمط: useLayoutEffect(() => { const rect = ref.current.getBoundingClientRect(); ... }, []). ولا يكون ref فارغًا داخل تأثير تخطيط على مكوّن تم تركيبه.

توقيت getBoundingClientRect

لماذا يُفضَّل استدعاء getBoundingClientRect() داخل useLayoutEffect بدلًا من useEffect؟

مراجعة الدرس: قياس عناصر DOM

استخدم getBoundingClientRect() داخل useLayoutEffect لقراءة قياسات DOM بعد التعديلات وقبل الرسم. وتؤدي تحديثات الحالة الناتجة عن هذه القياسات إلى إعادة تصيير متزامنة تُضمَّن في الرسم نفسه، مما يمنع الوميض. احمِ الشيفرة من SSR باستخدام فحص typeof window. ولتتبع تغيّر الحجم باستمرار، يُفضَّل استخدام ResizeObserver.

الأسئلة الشائعة

هل درس «قياس عناصر DOM باستخدام useLayoutEffect» مجاني؟

نعم — نص درس «قياس عناصر DOM باستخدام useLayoutEffect» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة React Academy، انتقل إلى CoddyKit PRO. تتضمن دورة React Academy 4 دروس في المجموع.

ماذا ستتعلم في «قياس عناصر DOM باستخدام useLayoutEffect»؟

اقرأ أبعاد العناصر ومواضعها وإزاحات التمرير بعد التخطيط وقبل الرسم لتجنّب الوميض تتمرن على React Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ React Academy؟

لا تُشترط خبرة سابقة. React Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «قياس عناصر DOM باستخدام useLayoutEffect»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس React Academy هذا؟

نعم. كل درس في React Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مرحلة العرض وتثبيت DOM
  2. متى يعمل useLayoutEffect مقارنةً بـ useEffect
  3. قياس عناصر DOM باستخدام useLayoutEffect
  4. تجنّب اضطراب التخطيط والوميض المرئي
← العودة إلى React Academy