0Pricing
React Academy · درس

تنفيذ Custom Hook باسم useThrottle

أنشئ hook باسم useThrottle يحدّ من تكرار تحديث قيمة أثناء الأحداث السريعة مثل التمرير

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

Throttle أصعب من Debounce

يعيد Debounce ضبط مؤقت ببساطة عند كل حدث. أما Throttle فيجب أن يتتبع بنشاط وقت آخر تنفيذ، ويقرر ما إذا كان قد مر وقت كافٍ لتنفيذ آخر. ويتطلب ذلك الاحتفاظ بطابع زمني بين عمليات إعادة التصيير، مما يجعل التنفيذ أكثر تعقيدًا قليلًا من Debounce.

استخدام useRef لتخزين lastRunTime

يجب أن يستمر الطابع الزمني لآخر تنفيذ عبر عمليات إعادة التصيير دون أن يتسبب هو نفسه في عمليات إعادة تصيير، مما يجعل useRef الأداة المناسبة. خزّن الطابع الزمني كما يلي: const lastRunTime = useRef(Date.now()). وعلى خلاف الحالة، لا يؤدي تحديث ref إلى إعادة التصيير، لذلك يعمل منطق Throttle بكفاءة دون دورات إضافية.

توقيع الخطاف

يعيد الخطاف useThrottle(value, delay) نسخة من قيمة الإدخال محدودة التواتر باستخدام Throttle. وتشبه واجهته التعاقدية واجهة useDebounce: إذ يقبل أي قيمة وتأخيرًا بالمللي ثانية، ثم يعيد القيمة محدودة التواتر. وتستخدمه المكوّنات بالطريقة نفسها، مما يجعله بديلًا مباشرًا بدلالات توقيت مختلفة.

تنفيذ throttle بالحافة اللاحقة

يحدّث throttle ذو الحافة اللاحقة القيمة في نهاية كل فترة زمنية. عند وصول قيمة جديدة، جَدولوا مؤقتًا باستخدام setTimeout للمدة المتبقية من الفترة: delay - (Date.now() - lastRunTime.current). عند انتهاء المؤقت، حدّثوا الحالة وسجّلوا قيمة lastRunTime الجديدة. ألغوا المؤقتات السابقة في دالة التنظيف.

تنفيذ throttle بالحافة الأمامية

يطبّق throttle ذو الحافة الأمامية القيمة الأولى فورًا، ويتجاهل القيم اللاحقة حتى انتهاء الفترة الزمنية. تحقّقوا مما إذا كان Date.now() - lastRunTime.current >= delay، ثم حدّثوا الحالة وسجّلوا الوقت. وإلا، فتجاوزوا التحديث. يوفّر هذا استجابة فورية عند الإجراء الأول، مع فترة تبريد تليه.

الجمع بين الحافتين الأمامية واللاحقة

غالبًا ما تجمع أفضل تجربة مستخدم بين الطريقتين: الاستجابة فورًا للحدث الأول (الحافة الأمامية)، ثم ضمان تطبيق الحالة النهائية أيضًا بعد انتهاء الفترة الزمنية (الحافة اللاحقة). يعني ذلك أن المستخدم يرى استجابة أولية سريعة، وأن القيمة النهائية المستقرة تُطبّق دائمًا بعد توقف الحركة، مما يمنع بقاء حالة نهائية قديمة.

استخدام useRef لمعرّف المؤقت

خزّنوا معرّف المؤقت المعلّق في useRef: const timeoutRef = useRef(null). قبل جدولة مؤقت جديد، استدعوا clearTimeout(timeoutRef.current) لإلغاء أي مؤقت موجود. يمنع هذا تداخل مؤقتات متعددة، كان من شأنه أن يسبب تحديثات متعددة ضمن فترة throttle واحدة.

التنظيف عند إلغاء تركيب المكوّن

ينبغي أن تستدعي دالة التنظيف في useEffect الدالة clearTimeout(timeoutRef.current) لإلغاء أي تحديث لاحق معلّق عند إلغاء تركيب المكوّن. ومن دون ذلك، قد ينتهي المؤقت المعلّق بعد إلغاء التركيب، ويحاول تحديث حالة مكوّن لم يعد مركّبًا، مما قد يؤدي إلى ظهور تحذيرات من React.

بديل الاستدعاء المقيّد

بدلًا من خطاف يعتمد على القيمة، يمكنكم إنشاء خطاف throttle يعتمد على useCallback: يعيد useThrottledCallback(fn, delay) نسخة مقيّدة من دالة. يكون هذا أكثر مرونة عندما تكون العملية التي تريدون تقييدها استدعاءً لدالة، مثل أداة لتتبّع التحليلات، بدلًا من قيمة تفاعلية.

اختبار throttle باستخدام المؤقتات الوهمية

في اختبارات Jest، استخدموا jest.useFakeTimers() للتحكم في الوقت. أعدّوا throttle بتأخير قدره 1000ms، ونفّذوا 10 تغييرات سريعة للقيمة، ثم قدّموا الوقت الوهمي بمقدار 500ms وتحقّقوا من حدوث تحديث واحد أو تحديثين فقط. قدّموا الوقت 500ms إضافية، وتحقّقوا من تنفيذ التحديث اللاحق. يتحقق هذا من سلوك throttle بطريقة حتمية.

throttle في نموذج React

يعالج React تحديثات الحالة على دفعات أثناء عمليات التصيير. ويعمل throttle الذي يُطبّق على تحديثات الحالة بانسجام مع هذا النموذج. لكن لاحظوا أنه في Concurrent Mode في React 18، قد تتم مقاطعة عمليات التصيير. أما منطق throttle نفسه، المستند إلى الوقت الفعلي المنقضي عبر Date.now()، فلا يتأثر بجدولة React.

الحافة اللاحقة أم الأمامية في throttle

على أي حافة ينفّذ throttle ذو «الحافة اللاحقة» عمله؟

مراجعة الدرس: خطاف useThrottle

يتطلب throttle تتبّع وقت آخر تنفيذ باستخدام useRef. ويمكن للخطاف تطبيق الحافة الأمامية (فوريًا)، أو الحافة اللاحقة (مؤجلًا)، أو كلتيهما. خزّنوا دائمًا معرّف المؤقت في مرجع وألغوه في دالة التنظيف. ولحالات الاستخدام المعتمدة على الدوال، يُفضّل اتباع نمط useThrottledCallback. اختبروا باستخدام المؤقتات الوهمية لضمان الموثوقية.

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

هل درس «تنفيذ Custom Hook باسم useThrottle» مجاني؟

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

ماذا ستتعلم في «تنفيذ Custom Hook باسم useThrottle»؟

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

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

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

كم من الوقت يستغرق درس «تنفيذ Custom Hook باسم useThrottle»؟

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

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

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

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

  1. أهمية Debounce وThrottle في واجهات المستخدم
  2. تنفيذ Custom Hook باسم useDebounce
  3. تنفيذ Custom Hook باسم useThrottle
  4. تطبيقات عملية: البحث والتمرير وتغيير الحجم
← العودة إلى React Academy