🚀 دليلك الشامل لاحتراف الـ Custom Hooks في React

حتى الآن، تعلمت استخدام الـ Hooks الأساسية التي توفرها لنا ريأكت مثل useState و useEffect. ولكن، ماذا لو وجدت نفسك تكتب نفس المنطق (Logic) في أكثر من مكون (Component)؟

هنا يأتي دور الـ Custom Hooks! فهي تمنحك القدرة على استخراج "المنطق" من المكونات ووضعه في مكان مستقل، لتعيد استخدامه في أي مكان آخر في تطبيقك بكل سهولة. ♻️


🧐 ما هي الـ Custom Hook بالضبط؟

ببساطة، الـ Custom Hook هي دالة (Function) عادية من دالالت جافاسكريبت، ولكنها تتميز بشيئين أساسيين:

  1. تبدأ بكلمة use: يجب أن يبدأ اسم الدالة بكلمة use (مثل useFetch أو useAuth). هذا ليس مجرد اتفاق، بل هو أمر ضروري لكي تعرف ريأكت أن هذه الدالة تحتوي على Hooks أخرى بداخلها.
  2. تستخدم Hooks أساسية: بداخل هذه الدالة، يمكنك استخدام useState و useEffect وأي Hooks أخرى لإنشاء منطق معين ثم إرجاع النتيجة للمكون.

لماذا نستخدمها؟

  • منع التكرار (DRY - Don't Repeat Yourself): بدلاً من كتابة نفس الكود في 5 مكونات، تكتبه مرة واحدة في Hook وتستدعيه 5 مرات.
  • تنظيم الكود: يصبح المكون (Component) نظيفاً ومركزاً فقط على عرض الواجهة (UI)، بينما ينتقل المنطق البرمجي إلى الـ Hook.

🛠️ كيف نبني Custom Hook خطوة بخطوة؟

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

بدلاً من كتابة useState في كل صفحة، سننشئ Hook اسمها useToggle.

الخطوة 1: إنشاء ملف الـ Hook

سنقوم بإنشاء دالة تأخذ قيمة ابتدائية وترجع الحالة والدالة التي تغير هذه الحالة.

// useToggle.js
import { useState } from 'react';

function useToggle(initialValue = false) {
  // تعريف الحالة داخل الـ Hook
  const [value, setValue] = useState(initialValue);

  // دالة لتبديل القيمة بين true و false
  const toggle = () => {
    setValue(!value);
  };

  // إرجاع القيمة والدالة لكي يستخدمهما المكون
  return [value, toggle];
}

export default useToggle;

الخطوة 2: استخدام الـ Hook داخل المكون

الآن، سنقوم باستدعاء هذه الـ Hook في أي مكون نحتاجه. لاحظ كيف أصبح الكود داخل المكون مختصراً جداً!

// App.js
import React from 'react';
import useToggle from './useToggle'; // استيراد الـ Custom Hook

function App() {
  // استخدام الـ Hook لإدارة حالة القائمة الجانبية
  const [isMenuOpen, toggleMenu] = useToggle(false);
  
  // استخدام نفس الـ Hook لإدارة حالة الوضع الليلي
  const [isDarkMode, toggleDarkMode] = useToggle(false);

  return (
    <div style={{ background: isDarkMode ? '#333' : '#fff', color: isDarkMode ? '#fff' : '#000' }}>
      <h1>Welcome to Codex Academy 🎓</h1>
      
      {/* زر التحكم في القائمة */}
      <button onClick={toggleMenu}>
        {isMenuOpen ? 'Close Menu ❌' : 'Open Menu ☰'}
      </button>

      {/* زر التحكم في الوضع الليلي */}
      <button onClick={toggleDarkMode}>
        {isDarkMode ? 'Switch to Light Mode ☀️' : 'Switch to Dark Mode 🌙'}
      </button>
    </div>
  );
}

export default App;

⚠️ ملاحظات هامة جداً للمبتدئين

لكي تنجح في استخدام الـ Custom Hooks، تذكر القواعد التالية:

  1. لا تستخدم الـ Hooks داخل جمل شرطية (If) أو حلقات تكرار (Loops): يجب دائماً استدعاء الـ Custom Hook في المستوى الأعلى (Top Level) من المكون.
  2. تسمية الدالة: إذا سميت الدالة myHook بدلاً من useMyHook فقد لا تعمل بشكل صحيح وقد لا تكتشف ريأكت الأخطاء المتعلقة بالـ Hooks.
  3. استقلالية الحالة: تذكر أن كل مكون يستدعي الـ Custom Hook يحصل على "نسخة مستقلة" من الحالة. في المثال السابق، تغيير isMenuOpen لا يؤثر أبداً على isDarkMode رغم أنهما يستخدمان نفس الـ Hook.

🎯 ملخص الدرس

  • الـ Custom Hooks هي وسيلة لإعادة استخدام المنطق البرمجي بين المكونات.
  • يجب أن تبدأ الأسماء بكلمة use.
  • تساعدنا في جعل المكونات أصغر حجماً وأسهل في القراءة.
  • هي مجرد دالة جافاسكريبت تستخدم بداخلها Hooks أخرى.