Menu
flag Ar iconالعربيةdown icon

الخطافات المخصصة في React: كيف تكتب خطافك الخاص مع أمثلة

الخطاف المخصص دالة يبدأ اسمها بـ use وتستدعي خطافات أخرى، لتتمكن عدة مكوّنات من إعادة استخدام المنطق ذي الحالة نفسه. ابنِ useToggle وuseLocalStorage وuseDebounce وuseWindowWidth، وتعلّم لماذا يحصل كل استدعاء على حالته الخاصة.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

الخطاف المخصص دالة يبدأ اسمها بـ use وتستدعي خطافات أخرى. تكتب واحدًا عندما يحتاج مكوّنان إلى المنطق ذي الحالة نفسه: انقل استدعاءات useState وuseEffect إلى الدالة، وأرجع ما يحتاجه المكوّن، واستدعِها من كل مكوّن.

يستدعي كلا عنصري الإخفاء useToggle، وفتح أحدهما يترك الآخر مغلقًا. كل استدعاء يشغّل useState الخاص به، فيحصل كل مكوّن على قيمته الخاصة. الخطاف المخصص يشارك المنطق لا الحالة.

قواعد كتابة خطاف

  • يبدأ الاسم بـ use يليها حرف كبير: useToggle وuseOnlineStatus. تستخدم قاعدة الفحص الخاصة بالخطافات البادئة لتجد استدعاءات الخطافات وتفحصها.
  • يستدعي خطافًا واحدًا على الأقل. الدالة المساعدة التي لا تستدعي أي خطاف دالة عادية؛ سمّها formatDate لا useFormatDate، ليمكن استدعاؤها في أي مكان، بما في ذلك داخل الشروط.
  • يتبع قواعد الخطافات: يستدعي الخطافات في مستواه الأعلى، ولا يُستدعى إلا من مكوّنات أو من خطافات مخصصة أخرى.
  • يُرجع كل ما هو مفيد. المصفوفة ([on, toggle]) مفيدة عندما يعيد المستدعون تسمية القيم؛ والكائن ({ data, loading, error }) أوضح لثلاث قيم أو أكثر.

useLocalStorage: حالة تبقى بعد إعادة التحميل

ينسى useState كل شيء عند إعادة التحميل. يقرأ هذا الخطاف القيمة الابتدائية من localStorage ويكتب كل تغيير فيه.

تعمل المعاينة في إطار معزول يحظر فيه المتصفح localStorage، لذا سترى هنا التحذير في Console ويعود الخطاف إلى حالة عادية. أما في صفحة عادية فيبقى الاسم بعد إعادة التحميل. وكتلة try/catch ليست لهذه المعاينة فقط: أوضاع التصفح الخاص وملفات تعريف الارتباط المحظورة والحصة الممتلئة كلها تجعل التخزين يرمي خطأ في التطبيقات الحقيقية أيضًا. وتمرير دالة إلى useState يعني أن التخزين يُقرأ مرة واحدة، في العرض الأول.

useDebounce: انتظر حتى يتوقف المستخدم عن الكتابة

ينبغي ألا يطلق مربع البحث طلبًا مع كل ضغطة مفتاح. يُرجع useDebounce نسخة من قيمة لا تتحدث إلا بعد أن تتوقف عن التغير لمهلة محددة.

اكتب كلمة بسرعة: يتبع Typed كل مفتاح، ويلحق Debounced بعد نصف ثانية من توقفك، وتسجّل Console بحثًا واحدًا. كل ضغطة مفتاح تغيّر value، فتشغّل React دالة التنظيف (clearTimeout) قبل بدء مؤقت جديد. غيّر 500 إلى 0 فتسجّل كل ضغطة مفتاح بحثها الخاص.

useWindowWidth: اشترك مع التنظيف

الخطاف الذي يستمع إلى المتصفح يجب أن يزيل مستمعه عندما يزول المكوّن، وإلا ترك كل تركيب مستمعًا خلفه.

غيّر حجم نافذة المتصفح فيتبعه الرقم. انقر الزر فتُظهر Console إزالة المستمع. احذف return من التأثير، ثم ركّب وأزل بضع مرات: تحصل على سطر added في كل مرة ولا سطر removed، فتتراكم المستمعات القديمة. ولقيم المتصفح مثل هذه، useSyncExternalStore هو الخطاف الذي بنته React لهذه المهمة، ومن الجيد استدعاؤه داخل خطاف مخصص.

المنطق مشترك، والحالة ليست كذلك

مكوّنان يستدعيان الخطاف نفسه يحصلان على نسختين منفصلتين من كل ما بداخله. وهذا يفاجئ من يتوقعون أن يعمل الخطاف كمتغير عام.

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

متى تكتب خطافًا مخصصًا

استخرج خطافًا عندما تظهر المجموعة نفسها من استدعاءات الخطافات في مكوّنين، أو عندما يطول منطق التأثير في مكوّن واحد بحيث يشرحه اسم بشكل أفضل (useOnlineStatus() أوضح من عشرين سطرًا من المستمعات). لا تغلّف استدعاء useState واحدًا في خطاف لمجرد إعادة تسميته، ولا تكتب خطافات لا تفعل سوى استدعاء useEffect لضبط الحالة من props؛ بل احسب تلك القيمة أثناء العرض.

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

ما هو الخطاف المخصص في React؟

دالة JavaScript يبدأ اسمها بـ use وتستدعي خطافًا آخر أو أكثر. تجمع المنطق ذا الحالة (الحالة والتأثيرات والمراجع) ليتمكن أي مكوّن من إعادة استخدامه باستدعاء الدالة.

هل تشارك الخطافات المخصصة الحالة بين المكوّنات؟

لا. كل استدعاء لخطاف مخصص يشغّل استدعاءات useState وuseEffect الخاصة به، فيحصل كل مكوّن على حالة مستقلة. ولمشاركة القيمة نفسها بين المكوّنات، ارفع الحالة أو ضعها في سياق أو مخزن خارجي.

لماذا يجب أن يبدأ اسم الخطاف المخصص بـ use؟

يخبر الاسم قواعد الفحص في React والمطورين الآخرين بأن الدالة تستدعي خطافات، فتنطبق عليها قواعد الخطافات: استدعِها في المستوى الأعلى، ولا تستدعها أبدًا داخل شرط أو حلقة. ومن دون البادئة لا تستطيع أداة الفحص التحقق من الاستدعاءات بداخلها.

هل يمكن للخطاف المخصص أن يُرجع JSX؟

يمكنه أن يُرجع أي شيء، لكن إذا أرجع JSX فمن الأفضل عادة كتابته كمكوّن. تُرجع الخطافات المخصصة عادة قيمًا ودوال، كمصفوفة ([value, toggle]) أو ككائن ({ data, error, loading }).

هل يمكنني استدعاء خطاف مخصص داخل useEffect أو معالج حدث؟

لا. الخطاف المخصص ما زال خطافًا، فيتبع قواعد الخطافات: استدعِه في المستوى الأعلى من مكوّن أو من خطاف مخصص آخر.

رسم توضيحي للغات البرمجة في Coddy

تعلّم البرمجة مع Coddy

ابدأ الآن