⏱️ جاري الحساب…

شرح React Hooks في ووردبريس: إدارة الحالة والآثار الجانبية والتنظيف في Gutenberg

رسم مفاهيمي يوضح React Hooks في ووردبريس ضمن سلسلة تطوير ووردبريس
📋 فهرس محتويات المقال (اضغط للتنقل السريع) ▾

أهلاً بيك يا صديقي المطور في عصب البرمجة الحديثة داخل محرر Gutenberg: React Hooks في بيئة ووردبريس.

من أول ما ظهرت خطافات React (React Hooks) في الإصدار 16.8، وطريقة كتابة واجهات الويب اتغيرت 180 درجة. وداعاً لكلاسات JavaScript القديمة (Class Components) ودوال componentDidMount و componentWillUnmount المعقدة، وأهلاً بالدوال النقية البسيطة والخطافات اللي بتمكنك من إدارة الحالة (State)، والاتصال بالـ APIs الخارجية، ومراقبة تغيرات الشاشة في سطور معدودة وواضحة وضوح الشمس.

في ووردبريس، الموضوع أخد بعد أعمق؛ لإن النواة وفرت حزمة كاملة اسمها @wordpress/element بتصدر كافة خطافات React الرسمية، بالإضافة لحزم تانية زي @wordpress/compose اللي بتقدم خطافات مخصصة لحل مشاكل لوحة التحكم المعقدة (زي useDebounce و useInstanceId). في المقال ده، هنشرح الفلسفة العميقة للهوكس، إزاي تدير الآثار الجانبية (Side Effects) بـ useEffect باحترافية، السر الخطير وراء دالة التنظيف (Cleanup Function) لمنع تسريب الذاكرة (Memory Leaks)، ودراسة حالة حقيقية لمنصة زراعية بالدلتا بالعامية المصرية التقنية الأصيلة.

الخطاف (Hook)الوظيفة المعمارية الأساسيةمتى يتم استدعاؤه؟هل يتطلب دالة تنظيف (Cleanup)؟أكبر خطأ شائع يقع فيه المطورون
useStateإدارة حالة محلية عابرة خاصة بواجهة المكون (Local UI State).عند كل رندرة، مع الاحتفاظ بآخر قيمة مسجلة في الذاكرة.لا؛ تديره React تلقائياً في الذاكرة.تعديل القيمة مباشرة (Mutation) بدلاً من استدعاء دالة التحديث.
useEffectتنفيذ الآثار الجانبية: جلب بيانات، ضبط مؤقتات، والاشتراك بالأحداث.بعد انتهاء مرحلة الـ Render والـ Commit على الشاشة.نعم حتماً عند استخدام مؤقتات أو اشتراكات أو طلبات شبكة.نسيان مصفوفة الاعتماديات (Dependencies) مما يسبب حلقات لانهائية.
useRefالاحتفاظ بمرجع ثابت لعنصر DOM أو قيمة متغيرة لا تتطلب إعادة رسم.ثابت عبر كافة دورات حياة المكون دون إطلاق Re-render.لا يحتاج، ولكنه يتطلب تصفير المراجع عند الـ Unmount إذا لزم.استخدامه كبديل لـ useState للبيانات التي يجب أن تظهر في الـ JSX فوراً.
useMemoتخزين نتيجة عملية حسابية مكلفة في الذاكرة (Memoization).أثناء مرحلة الرندرة فقط إذا تغيرت قيم الاعتماديات.لا يتطلب دالة تنظيف.استخدامه مع عمليات حسابية تافهة مما يزيد من العبء المعماري.
useCallbackالاحتفاظ بمرجع ثابت لدالة معينة لتمريرها للأطفال المحصنين بـ memo.يعيد نفس مرجع الدالة طالما أن الاعتماديات لم تتغير.لا يتطلب دالة تنظيف.نسيان وضع المتغيرات المستخدمة داخل الدالة في مصفوفة الاعتماديات.

تشريح خطاف useEffect: إدارة الآثار الجانبية ودالة التنظيف المقدسة

لو فيه مفهوم واحد لو فهمته صح هتتحول لمهندس برمجيات محترف، فهو: Side Effects & Cleanup Function. المكون في React وظيفته الأصلية والوحيدة إنه ياخد Props ويرجع JSX (واجهة بصرية). أي عملية تانية بتتعامل مع “العالم الخارجي” بنسميها Side Effect، زي:

  • إرسال طلب HTTP عبر fetch لجلب درجات الحرارة أو أسعار الذهب.
  • تشغيل مؤقت زمني setInterval لتحديث عداد كل ثانية.
  • الاستماع لحركة الفأرة أو تغيير مقاس الشاشة window.addEventListener('resize', ...).

مصفوفة الاعتماديات (Dependency Array): صمام أمان المعالج

دالة useEffect بتاخد وسيطين: دالة التأثير، ومصفوفة الاعتماديات:

  1. بدون مصفوفة نهائياً (useEffect(() => {})):

    ⚠️ انتحار برمجي! سيعمل التأثير مع كل حرف يكتبه المستخدم في أي مكان بالصفحة، مما يعطل المتصفح تماماً.

  2. مصفوفة فارغة (useEffect(() => {}, [])):

    يعمل التأثير مرة واحدة فقط عند ولادة المكون على الشاشة (Component Mount)، وهو المكان المثالي لجلب البيانات الأولية.

  3. مصفوفة تحتوي على متغيرات (useEffect(() => {}, [cityName])):

    يعمل التأثير عند ولادة المكون، وكلما تغيرت قيمة cityName فقط.

دالة التنظيف (The Cleanup Function): لماذا يتسرب الرام بدونها؟

تخيل إنك شغلت setInterval بيعمل طلب للـ API كل 10 ثواني. المحرر قرر يمسح البلوك ده من المقال (Unmount). لو أنت مش كاتب دالة تنظيف، المؤقت هيفضل شغال في خلفية المتصفح للأبد، وهيحاول يحدث بيانات مكون ميت ومحذوف من الشاشة، وتفاجأ برسالة الخطأ الشهيرة في الكونسول: “Warning: Can’t perform a React state update on an unmounted component” مع تسريب خطير في الذاكرة (Memory Leak).

الحل هو إرجاع دالة بسيطة من داخل useEffect تتكفل بإلغاء المؤقتات ومسح الاشتراكات:

useEffect( () => {
    // 1. بدء التأثير الجانبي
    const timer = setInterval( () => {
        console.log( 'نبضة تحديث في الخلفية...' );
    }, 5000 );

    // 2. دالة التنظيف المقدسة (Cleanup)
    return () => {
        clearInterval( timer ); // تنظيف فوري عند حذف البلوك أو إعادة تشغيل التأثير!
    };
}, [] );

تطبيق عملي كامل: بلوك نشرة الطقس والري مع AbortController وتنظيف المؤقتات

تعال نبني مع بعض كود إنتاجي لبلوك مؤشرات الطقس الزراعي (enterprise/weather-monitor) يوضح كيف نستخدم useState، useEffect، useRef، وتقنية AbortController لإلغاء طلبات الشبكة المعلقة في حالة قيام المحرر بتغيير المدينة سريعاً أو حذف البلوك:

1. إعداد ملف block.json

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "enterprise/weather-monitor",
  "version": "1.0.0",
  "title": "مؤشر الطقس الزراعي اللحظي",
  "category": "widgets",
  "icon": "cloud",
  "attributes": {
    "selectedCity": {
      "type": "string",
      "default": "Cairo"
    },
    "refreshIntervalSeconds": {
      "type": "number",
      "default": 30
    }
  },
  "editorScript": "file:./index.js",
  "style": "file:./style-index.css"
}

2. كود واجهة التحرير: edit.js المحصن بدوال التنظيف وإلغاء الطلبات

import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, SelectControl, RangeControl, Spinner, Notice } from '@wordpress/components';
import { useState, useEffect, useRef } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import './editor.scss';

export default function Edit( { attributes, setAttributes } ) {
    const { selectedCity, refreshIntervalSeconds } = attributes;

    // حالات محلية خاصة بواجهة المستخدم
    const [ weatherData, setWeatherData ] = useState( null );
    const [ isLoading, setIsLoading ] = useState( false );
    const [ errorMessage, setErrorMessage ] = useState( '' );

    // مرجع للاحتفاظ بعداد الاستدعاءات بدون إطلاق إعادة رسم
    const fetchCountRef = useRef( 0 );

    const blockProps = useBlockProps( {
        className: 'az-weather-monitor-box'
    } );

    useEffect( () => {
        // إنشاء وحدة تحكم لإلغاء الطلب الشبكي إذا تم حذف البلوك أو تغيرت المدينة (AbortController)
        const abortController = new AbortController();
        const signal = abortController.signal;

        const fetchLiveWeather = async () => {
            setIsLoading( true );
            setErrorMessage( '' );

            try {
                // محاكاة استدعاء API الطقس الحقيقي مع تمرير إشارة الإلغاء
                fetchCountRef.current += 1;
                
                // استبدل هذا الرابط بنقطة النهاية الحقيقية لموقعك
                const response = await fetch( `https://api.example.com/weather?city=${ encodeURIComponent( selectedCity ) }`, {
                    signal: signal // ربط الطلب بالإشارة
                } );

                if ( ! response.ok ) {
                    throw new Error( 'فشل في الاتصال بمحطة الرصد الجوي' );
                }

                const data = await response.json();
                setWeatherData( data );
            } catch ( err ) {
                // إذا كان سبب الخطأ هو إلغاء الطلب يدوياً، لا نظهر رسالة خطأ
                if ( err.name !== 'AbortError' ) {
                    // بيانات احتياطية آمنة في حالة فشل المحاكاة
                    setWeatherData( {
                        city: selectedCity,
                        temp: selectedCity === 'Cairo' ? 32 : 28,
                        humidity: 55,
                        status: 'مشمس ومعتدل',
                    } );
                }
            } finally {
                setIsLoading( false );
            }
        };

        // 1. تشغيل الجلب الأولي فوراً
        fetchLiveWeather();

        // 2. ضبط مؤقت التحديث الدوري بناءً على الإعدادات
        const intervalId = setInterval( () => {
            fetchLiveWeather();
        }, refreshIntervalSeconds * 1000 );

        // 3. دالة التنظيف المقدسة (Cleanup Function)
        return () => {
            abortController.abort(); // إلغاء أي اتصال HTTP معلق فوراً
            clearInterval( intervalId ); // إيقاف المؤقت ومنع استمراره في الخلفية
        };
    }, [ selectedCity, refreshIntervalSeconds ] ); // يعاد تشغيل التأثير فقط إذا تغيرت المدينة أو فترة التحديث!

    return (
        
setAttributes( { selectedCity: val } ) } /> setAttributes( { refreshIntervalSeconds: val } ) } min={ 10 } max={ 120 } step={ 5 } />

{ __( 'محطة الرصد الجوي المباشر', 'az-weather' ) }: { selectedCity }

{ __( 'عدد مرات الرصد: ', 'az-weather' ) } { fetchCountRef.current }
{ isLoading && (
{ __( 'جاري تحديث قراءات الرطوبة والرياح...', 'az-weather' ) }
) } { ! isLoading && errorMessage && ( { errorMessage } ) } { ! isLoading && weatherData && (
{ __( 'درجة الحرارة', 'az-weather' ) } { weatherData.temp }°C
{ __( 'نسبة الرطوبة', 'az-weather' ) } { weatherData.humidity }%
{ __( 'الحالة الجوية', 'az-weather' ) } { weatherData.status }
) }
); }

قواعد الهوكس الذهبية (The Golden Rules of Hooks)

نواة React تعتمد داخلياً على مصفوفة أحادية بسيطة لتتبع ترتيب الخطافات في الذاكرة. ولضمان عدم حدوث تضارب، يجب الالتزام بقاعدتين حديديتين:

  1. استدعاء الهوكس في المستوى الأعلى فقط (Top Level Only):

    لا تستدعِ خطافاً أبداً داخل جملة شرطية if (...)، أو داخل حلقة تكرار for / while، أو داخل دالة مجهولة فرعية! يجب أن تستدعى كل الخطافات في بداية جسم المكون مباشرة بنفس الترتيب في كل دورة رندرة.

  2. استدعاء الهوكس من دوال React فقط:

    لا تستدعِ الخطافات من دوال جافاسكريبت عادية؛ استدعها فقط من مكونات React الدالية (Function Components) أو من داخل خطافات مخصصة (Custom Hooks) تبدأ كلمتها بـ use....

دراسة حالة واقعية: كارثة منصة الدلتا للرصد الزراعي في طنطا والمنصورة

خلفية المشروع وأبعاد الأزمة

منصة تكنولوجية زراعية مصرية رائدة تقدم إرشادات الري والتسميد الذكي لمزارعي الدلتا (أكثر من 140,000 مزارع ومهندس زراعي مسجل في الغربية والدقهلية والبحيرة). الموقع يحتوي على بوابة إخبارية متقدمة يعمل عليها 12 محرراً زراعياً لنشر نصائح الطقس والري اليومية باستخدام بلوك Gutenberg مخصص يعرض “مؤشرات الطقس وسرعة الرياح الحية”.

الأزمة التشخيصية (The Crisis)

قام أحد المطورين ببرمجة طلب جلب بيانات الطقس عبر useEffect يحتوي على مؤقت setInterval يستدعي API خارجي مدفوع كل 30 ثانية:

  • المطور نسي تماماً كتابة دالة التنظيف return () => clearInterval(...)، ونسي تحديد مصفوفة الاعتماديات!
  • أثناء كتابة المحررين للمقالات ومراجعتها، كان كل محرر يفتح المقال، يغير اسم المحافظة 5 أو 6 مرات، أو يغلق التبويب ويفتحه مجدداً.
  • في كل مرة كان يتم فيها تغيير المدينة أو إعادة فتح المقال، كان ينشأ مؤقت جديد في الخلفية يعمل بالتوازي مع المؤقتات القديمة دون أن يتوقف أي منها!
  • خلال 4 ساعات فقط، كان هناك أكثر من 8,000 مؤقت زومبي (Zombie Timers) يعمل في خلفية متصفحات صالة التحرير، مما تسبب في تجمد كامل لأجهزة الكمبيوتر واستهلاك 100% من قدرة المعالجات.
  • الكارثة المالية الأكبر: استهلكت المؤقتات العالقة أكثر من 850,000 استدعاء API مدفوع في يوم واحد، وتلقت الشركة فاتورة طارئة بـ 3,200 دولار أمريكي مع إيقاف الحساب لتجاوز حد الاستهلاك اليومي!

الحل المعماري الجذري (The Architectural Solution)

تم استدعاء مهندس برمجيات أول لإصلاح الكارثة المعمارية فوراً:

  1. إضافة دالة تنظيف صارمة بداخل useEffect تقوم باستدعاء clearInterval(intervalId) عند إلغاء تحميل المكون.
  2. دمج تقنية AbortController لإلغاء طلبات الـ HTTP المعلقة في الهواء بمجرد تغيير المدينة أو إغلاق الصفحة.
  3. حصر مصفوفة الاعتماديات في [ selectedCity, refreshIntervalSeconds ] لمنع تكرار الاستدعاء مع كل ضغطة زر أو تعديل نصي مجاور.
  4. إضافة طبقة تخزين مؤقت سيرفرية (Transient Caching) على مستوى ووردبريس لمدة 15 دقيقة، بحيث لا يتم استدعاء الـ API الخارجي إلا مرة واحدة لكل محافظة لكل ربع ساعة مهما بلغ عدد المحررين.

جدول قياس مؤشرات الأداء والوفر المالي (Metrics Table)

مؤشر الأداء والتشغيلأثناء الأزمة (غياب دالة التنظيف)بعد الحل المعماري الصارمنسبة التحسن والوفر المحقق
عدد استدعاءات الـ API اليومية850,000 طلب عشوائي مكرر96 طلباً فقط في اليوم (مكوش بالكامل)تخفيض استهلاك الـ API بنسبة 99.98%
مؤقتات الذاكرة العالقة (Zombie Timers)8,000+ مؤقت يتسبب في تجمد المتصفحصفر مؤقتات عالقة (تنظيف لحظي 100%)استقرار تام لمتصفحات صالة التحرير
استهلاك معالج أجهزة التحرير (CPU Usage)100% مستمر مع دوران مراوح التبريدأقل من 4% أثناء الكتابة والتصفحتوفير طاقة المعالجة وتسريع الأداء
التكلفة المالية الشهرية لمزود الطقس3,200 دولار ديون وغرامات تجاوزالخطة المجانية الصفرية (Free Tier)وفر مالي سنوي يتجاوز 38,000 دولار

الوصايا العشر لاستخدام React Hooks في ووردبريس

  1. دائماً اكتب دالة التنظيف (Cleanup): إذا استخدمت setInterval، setTimeout، أو addEventListener داخل useEffect، فلا تغادر إلا بعد كتابة دالة الإلغاء في return.
  2. لا تهمل مصفوفة الاعتماديات: لا تترك useEffect بدون مصفوفة ثانية؛ حدد بدقة المتغيرات التي يستمع إليها التأثير.
  3. استخدم AbortController مع طلبات الـ fetch: ألغِ الاتصالات الشبكية المعلقة عند إلغاء تحميل المكون لمنع الأخطاء وتسريب الذاكرة.
  4. احترم ترتيب الهوكس الصارم: لا تضع useState أو useEffect داخل جمل شرطية أو حلقات تكرار.
  5. استخدم useRef للمتغيرات الصامتة: إذا كانت المعلومة تتغير ولكن لا تتطلب إعادة رسم الشاشة (مثل المعرفات أو العدادات)، استخدم useRef.
  6. وفر على المعالج بـ useMemo: خزن نتائج الفلترة والفرز في الجداول الكبيرة في الذاكرة لتجنب إعادة حسابها في كل رندرة.
  7. استخدم useCallback لتثبيت مراجع الدوال: خاصة عند تمرير دوال لمكونات فرعية مغلفة بـ memo للحفاظ على كفاءة الـ Caching.
  8. افصل المنطق المعقد في Custom Hooks: اجمع كود جلب البيانات وإدارتها في هوك مخصص يبدأ اسمه بـ use... لسهولة إعادة الاستخدام.
  9. لا تستخدم useState لتخزين محتوى المقال: المحتوى الدائم مكانه setAttributes، بينما useState مخصصة لحالة الواجهة العابرة فقط.
  10. فعل ESLint Plugin React Hooks: اعتمد على أدوات التدقيق الآلي لكشف نسيان الاعتماديات أو انتهاك قواعد الهوكس أثناء كتابة الكود.

معمارية بناء الـ Custom Hooks المخصصة في Gutenberg

يا صديقي المطور، العلامة الفارقة بين كتابة كود عشوائي وهندسة برمجية حقيقية هي قدرتك على استخراج الأنماط المتكررة في كودك وتحويلها إلى Custom React Hooks.

لو لاحظت إنك في كل بلوك بتبنيه، بتضطر تكتب كود جلب بيانات من الـ REST API، أو بتضطر تكتب منطق التحقق من حجم الشاشة، أو بتعمل تأخير للكتابة (Debouncing)؛ فنسخ ولصق نفس كود useEffect و useState في 10 بلوكات مختلفة هو جريمة تكرار كود (DRY Violation).

كود عملي متكامل: بناء خطاف مخصص useDebouncedAttribute

تعال نبني خطافاً مخصصاً فائق الأهمية في جوتنبرج؛ وظيفته إنه يستقبل القيمة اللي بيكتبها الكاتب في الـ RichText، ويؤخر استدعاء setAttributes لمدة 300 مللي ثانية حتى يتوقف الكاتب عن النقر السريع، مما يمنع إرهاق مخزن البيانات المركزي (Redux Store) بنبضات حفظ مستمرة:

/**
 * خطاف مخصص لتأخير حفظ الخصائص وتسريع الكتابة في Gutenberg
 * File: hooks/useDebouncedAttribute.js
 */
import { useState, useEffect, useRef } from '@wordpress/element';

export function useDebouncedAttribute( initialValue, onSaveAttribute, delay = 350 ) {
    // 1. حالة محلية سريعة جداً لمتابعة كل حرف يكتبه المستخدم في الشاشة
    const [ localValue, setLocalValue ] = useState( initialValue );
    
    // مرجع لتتبع أول رندرة للمكون لمنع حفظ القيمة المبدئية بلا داعٍ
    const isFirstRender = useRef( true );

    useEffect( () => {
        // تجاهل أول دورة رندرة عند فتح المقال
        if ( isFirstRender.current ) {
            isFirstRender.current = false;
            return;
        }

        // ضبط مؤقت لتحديث الخاصية المركزية بعد توقف الكاتب عن الضغط
        const handler = setTimeout( () => {
            onSaveAttribute( localValue );
        }, delay );

        // دالة التنظيف: إلغاء المؤقت فوراً إذا ضغط الكاتب حرفاً جديداً قبل انتهاء المهلة!
        return () => {
            clearTimeout( handler );
        };
    }, [ localValue, delay, onSaveAttribute ] );

    // مزامنة الحالة المحلية إذا تغيرت القيمة من مصدر خارجي (مثل Undo/Redo)
    useEffect( () => {
        setLocalValue( initialValue );
    }, [ initialValue ] );

    return [ localValue, setLocalValue ];
}

كيف تستخدم هذا الخطاف داخل البلوك بتاعك؟

import { useBlockProps, RichText } from '@wordpress/block-editor';
import { useDebouncedAttribute } from './hooks/useDebouncedAttribute';

export default function Edit( { attributes, setAttributes } ) {
    const blockProps = useBlockProps();
    
    // استخدام سطر واحد فقط لإدارة الكتابة فائقة السرعة مع حفظ مؤجل آمن!
    const [ title, setTitle ] = useDebouncedAttribute(
        attributes.title,
        ( debouncedVal ) => setAttributes( { title: debouncedVal } )
    );

    return (
        
); }

مقارنة معمارية: خطاف useId القياسي مقابل useInstanceId في ووردبريس

توليد معرّفات فريدة للربط بين وسوم <label> وحقول <input> كان دائماً صداعاً مزمناً في تطبيقات الـ SSR والرندرة المشتركة:

  • خطاف useInstanceId (المقدم من @wordpress/compose): يعتمد على عداد رقمي بسيط في الذاكرة الحية. مشكلته الأساسية أنه في بيئات المعالجة السيرفرية (SSR) قد يختلف الرقم التراكمي بين السيرفر والمتصفح مما يسبب أخطاء التحقق ومطابقة الـ Hydration.
  • خطاف useId (المدمج في React 18 ونواة ووردبريس الحديثة): يولد معرّفات نصية تعتمد على موضع المكون في الشجرة الهرمية (مثل: :r1:، :r2:). هذا الخطاف مضمون التطابق بنسبة 100% بين مخرجات السيرفر ومخرجات المتصفح، وهو الأسلوب الموصى به رسمياً لكافة البلوكات المصممة لبيئات الـ Full Site Editing والـ Headless WordPress.

الأسئلة الشائعة حول React Hooks في ووردبريس (20 سؤالاً وجواباً تفصيلياً)

1. من أين أستورد React Hooks داخل مشروع ووردبريس؟

من حزمة @wordpress/element الرسمية، مثل: import { useState, useEffect } from '@wordpress/element';.

2. ما هي وظيفة مصفوفة الاعتماديات (Dependencies Array) في useEffect؟

تحدد المتغيرات التي تراقبها React؛ فإذا لم تتغير أي قيمة داخل المصفوفة بين دورات الرندرة، تتجاوز React تنفيذ دالة التأثير لتوفير موارد الجهاز.

3. ماذا يحدث إذا تركت مصفوفة الاعتماديات فارغة تماماً []؟

سيتم تنفيذ كود useEffect لمرة واحدة فقط عند إنشاء المكون (Mounting)، وسيتم تنفيذ دالة التنظيف عند حذفه نهائياً (Unmounting).

4. ما هو تسريب الذاكرة (Memory Leak) وكيف تسببه الهوكس؟

يحدث عندما يظل كود الجافاسكريبت محتفظاً بمراجع لمكونات أو مؤقتات ملغاة في الذاكرة دون تنظيفها، مما يؤدي لتراكم استهلاك الرام وبطء المتصفح تدريجياً.

5. كيف أستخدم AbortController داخل useEffect؟

تنشئ نسخة جديدة منه وتمرر signal لطلب الـ fetch، وفي دالة التنظيف المرتجعة تستدعي controller.abort() لإلغاء الاتصال فوراً.

6. ما الفارق الجوهري بين useRef و useState؟

تعديل قيمة useState يطلق إعادة رسم للمكون في الشاشة (Re-render)، بينما تعديل useRef.current يغير القيمة بصمت في الذاكرة دون إعادة رسم الشاشة.

7. لماذا يحظر استدعاء الهوكس داخل جملة if الشرطية؟

لأن React تعتمد على الترتيب الحسابي الصارم لاستدعاء الخطافات لمطابقة كل حالة بمكانها؛ وإذا تم تخطي خطاف في دورة معينة، تنهار خوارزمية الربط بالكامل.

8. متى يجب علي استخدام useMemo؟

عندما تكون لديك عملية حسابية معقدة ومكلفة (مثل فرز مصفوفة تضم 10,000 عنصر)، وتريد تجنب تكرار هذا الحساب مع كل حركة بالواجهة طالما لم تتغير البيانات.

9. ما هي الخطافات المخصصة (Custom Hooks) في ووردبريس؟

هي دوال جافاسكريبت عادية تبدأ بكلمة use وتستخدم خطافات React بداخلها لتغليف وتجريد منطق برمجي معين (مثل الاتصال بمخازن البيانات أو جلب الإعدادات).

10. كيف أتعامل مع تحذير “Can’t perform a React state update on an unmounted component”؟

بإضافة دالة تنظيف (Cleanup) داخل useEffect تلغي أي عمليات غير متزامنة أو مؤقتات جارية قبل فوات الأوان.

11. هل يمكن استخدام أكثر من useEffect داخل نفس المكون؟

نعم بكل تأكيد؛ ويُنصح هندسياً بفصل التأثيرات غير المترابطة في دوال useEffect متعددة بدلاً من حشرها جميعاً في دالة واحدة.

12. ما هو خطاف useDebounce ومتى نحتاجه في جوتنبرج؟

هو خطاف من حزمة @wordpress/compose يؤخر تنفيذ دالة معينة (مثل البحث أو الحفظ) حتى يتوقف المستخدم عن الكتابة لمهلة محددة، مما يمنع إرهاق السيرفر.

13. كيف أحصل على القيمة السابقة لخاصية معينة (Previous Value)؟

باستخدام خطاف usePrevious من حزمة @wordpress/compose الذي يحتفظ بالقيمة المسجلة في الرندرة السابقة.

14. هل خطافات React تعمل داخل ملف render.php في السيرفر؟

لا إطلاقاً؛ خطافات React هي كود جافاسكريبت يعمل حصرياً في متصفح العميل، بينما ملف render.php كود PHP يعمل على خادم السيرفر.

15. ما هي وظيفة خطاف useInstanceId في ووردبريس؟

يولد معرّفاً رقمياً فريداً ومتزايداً لكل نسخة من المكون على الشاشة، ويستخدم بشكل أساسي لربط وسوم label بحقول الإدخال لتفادي تكرار الـ IDs.

16. كيف أمنع useEffect من الدخول في حلقة لانهائية (Infinite Loop)؟

بالتأكد من أن الدالة لا تقوم بتحديث أي متغير مدرج داخل مصفوفة الاعتماديات الخاصة بها بشكل مباشر وغير مشروط.

17. ما الفارق بين useEffect و useLayoutEffect؟

الـ useLayoutEffect يتنفذ تزامناً قبل أن يقوم المتصفح بطلاء الشاشة، ويستخدم لقياس أبعاد عناصر الـ DOM لتفادي وميض الواجهة (Flicker)، بينما useEffect يعمل بعد الطلاء.

18. هل يمكن لـ useEffect أن تكون دالة async مباشرة؟

لا يجوز كتابة useEffect(async () => ...) لأن دالة التأثير يجب أن ترجع دالة تنظيف فقط؛ والحل هو تعريف دالة async داخلية واستدعاؤها في الحال.

19. كيف أربط مرجع useRef بعنصر HTML حقيقي؟

بتمريره في خاصية ref على الوسم في الـ JSX: <div ref={myRef}>، ويمكنك بعد ذلك الوصول للعنصر عبر myRef.current.

20. ما هي القاعدة الذهبية للمطورين عند كتابة خطافات React في ووردبريس؟

“اجعل دوالك نقية، وحدد اعتمادياتك بصرامة، ولا تفتح اتصالاً أو مؤقتاً في التأثير دون أن تغلقه بدالة تنظيف محكمة”.

الصورة الرمزية لـ Mohamed Abozaid

م. محمد أبو زيد

WordPress Architect & Enterprise Consultant

مهندس برمجيات متخصص في تطوير حلول ووردبريس المتقدمة، معمارية Block Themes، ومحرر Gutenberg، وتحسين الأداء لمواقع الشركات الكبرى في مصر والخليج العربي.


اترك تعليقاً