في هذا الدرس 6تصفّح المواضيع
عندما يحتاج المكون إلى تذكر بيانات تظهر للمستخدم على الشاشة نعتمد على useState كي تعيد React رسم الواجهة مع كل تحديث. غير أن المكونات تحتاج أحياناً إلى تذكر قيم داخلية خلف الكواليس — مثل معرّف مؤقت نشط أو طابع زمني سابق أو عداد تشخيصي — لا يغير تعديلها شكل العناصر المرسومة إطلاقاً.
هنا توفر مكتبة React خطاف useRef بوصفه منفذاً هندسياً صامتاً (Escape Hatch) يحتفظ بالقيمة بين مرات التصيير المتتالية دون أن يطلب إعادة تصيير المكون عند الكتابة فيه.
const silentClicksRef = useRef(0);
const [report, setReport] = useState('No snapshot yet');
function handleSilentClick() {
silentClicksRef.current += 1;
}
function handleReveal() {
setReport('Saved in ref: ' + silentClicksRef.current);
}
عند استدعاء useRef(initialValue) تعيد React كائن JavaScript بسيطاً يحمل خاصية وحيدة بالشكل { current: initialValue }. وعلى عكس لقطات الحالة الثابتة، تظل هوية هذا الكائن في الذاكرة ثابتة ومطابقة لنفسها في كل تصيير يمر به المكون.
يمكنك قراءة خاصية ref.current وتعديلها مباشرة بالإسناد الاعتيادي دون الحاجة لدالة ضبط خاصة، لأن React تتعمد عدم مراقبة تغييراتها لإعادة الرسم.
يبرز المثال العملي الأشهر للمراجع القيمية في بناء ساعة الإيقاف والمتحكمات الزمنية؛ إذ يحتاج عرض الوقت المتصاعد على الشاشة إلى useState، بينما يتطلب زر الإيقاف الاحتفاظ بالمعرّف الرقمي الذي تعيده دالة setInterval() لتمريره لاحقاً إلى clearInterval().
ولأن المستخدم قد يضغط زر الإيقاف بعد عشرات التحديثات المتتالية للعداد، فإن تخزين المعرّف في intervalRef.current يضمن بقاءه سالماً وجاهزاً للإلغاء الفوري.
const [tenths, setTenths] = useState(0);
const intervalRef = useRef(null);
function handleStart() {
clearInterval(intervalRef.current);
intervalRef.current = setInterval(() => {
setTenths((t) => t + 1);
}, 100);
}
تفرض React قاعدة ذهبية حاسمة عند استخدام المراجع: لا تقرأ أو تعدّل ref.current أثناء تنفيذ جسم التصيير مطلقاً؛ إذ يجب أن تبقى دالة المكون دالة نقية تعتمد مخرجاتها البصرية على props وstate وحدهما.
- ممنوع أثناء العرض: كتابة
ref.current += 1في جسم المكون أو وضع{ref.current}مباشرة داخل عناصرJSXلأن القيمة لن تتحدث تلقائياً وستختل تحت فحصStrictMode. - النطاق الآمن: قراءة وتعديل
ref.currentداخل معالجات الأحداث مثلonClickوonSubmit.
تتألق المراجع الصامتة كذلك في رصد إيقاع تفاعل المستخدم — مثل قياس الفارق الزمني بالمللي ثانية بين نقرتين متتاليتين أو منع الإرسال المزدوج السريع — دون إرهاق المتصفح بإعادات رسم متلاحقة لتفاصيل داخلية.
const lastTapRef = useRef(0);
const [gapText, setGapText] = useState('Tap twice!');
function handleTap() {
const now = Date.now();
if (lastTapRef.current > 0) {
setGapText((now - lastTapRef.current) + ' ms gap');
}
lastTapRef.current = now;
}
قبل الاختيار بين الخطافين اطرح سؤالاً هندسياً واحداً: هل يتطلب تغير هذه القيمة تحديث ما يراه المستخدم على الشاشة؟ إن كانت الإجابة نعم فاستخدم useState، وإن كانت معلومة تشغيلية داخلية فاستخدم useRef. يوضح الجدول التالي الفروق الدقيقة:
| وجه المقارنة | خطاف الحالة useState | خطاف المرجع useRef |
|---|---|---|
| بنية القيمة المعادة | مصفوفة ثنائية تضم القيمة ودالة التحديث | كائن ثابت يضم خاصية current القابلة للتعديل |
| تحفيز إعادة التصيير | نعم، يجدول إعادة رسم المكون عند تغير القيمة | لا، تعديل current يتم بصمت تام دون رسم |
| قابلية التعديل المباشر | غير قابلة للتعديل المباشر بل عبر دالة الضبط | قابلة للتعديل الفوري المباشر داخل دوال الأحداث |
| القراءة أثناء العرض | آمنة وأساسية لتكوين عناصر واجهة JSX | ممنوعة أثناء العرض وتُقرأ في معالجات الأحداث |
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
أتقنت في هذا الدرس حفظ القيم الداخلية المتغيرة بخطاف useRef، وفهمت بنية الكائن المستمر ذي خاصية current، وبنيت ساعة إيقاف دقيقة تحفظ معرف المؤقت بأمان، والتزمت بقاعدة نقاء العرض ومقارنة المرجع مع useState. الخطوة التالية: انتقل الآن إلى الدرس رقم 33 «التعامل المباشر الآمن مع عناصر DOM عبر المراجع» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Ref Container حاوية المرجع
- كائن JavaScript مستمر الهوية يضم خاصية current قابلة للتعديل تحتفظ بها React طوال بقاء المكون.
- للمراجعة
- 02 Escape Hatch منفذ الخروج الآمن
- آلية في React تتيح للمكون حفظ قيم صامتة أو التخاطب مع واجهات المتصفح الأمرية خارج دورة الرسم.
- للمراجعة
- 03 Silent Mutation التعديل الصامت
- تحديث قيمة ref.current مباشرة داخل معالج حدث دون التسبب في جدولة إعادة تصيير للمكون.
- للمراجعة
- 04 Interval Handle معرّف المؤقت الدوري
- الرقم التعريفي الذي تعيده دالة setInterval ويلزم حفظه في مرجع لإيقاف المؤقت لاحقاً عبر clearInterval.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 API API
- Application Programming Interface
- واجهات البرمجة المدمجة في المتصفح مثل دوال المؤقتات والزمن التي نتعامل معها داخل دوال الأحداث.
- للمراجعة
- 02 UI UI
- User Interface
- طبقة العرض المرئية للمستخدم والتي تقودها الحالة والخصائص لا المراجع الصامتة.
- للمراجعة
- 03 ID ID
- Identifier
- معرّف فريد يمثل مؤقتاً نشطاً في المتصفح لتمكين إلغائه بدقة عند الطلب.
- للمراجعة
- 04 JSX JSX
- JavaScript XML
- صياغة توصيف الواجهة في React والتي يجب أن تقرأ الحالة والخصائص بنقاء دون قراءة ref.current.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
افتح مثال ساعة الإيقاف في محرر التجريب، وتأكد من عمل الإيقاف عبر intervalRef.current ثم أضف زر تسجيل جولة يعرض أزمنة الجولات في الحالة.
-
عدّل مثال قياس إيقاع النقر بحيث يعرض تنبيهاً خاصاً عندما يكون الفارق الزمني المحفوظ في المرجع أقل من 300 مللي ثانية.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي10 أسئلة تنتظرك +
ما القيمة الدقيقة التي يعيدها استدعاء useRef(0) داخل المكون؟
يعيد خطاف useRef كائناً ثابت الهوية يحتوي على خاصية واحدة اسمها current مهيأة بالقيمة 0.
يؤدي إسناد قيمة جديدة إلى خاصية ref.current إلى جدولة إعادة تصيير للمكون تلقائياً.
خطأ؛ فتعديل خاصية ref.current يتم بصمت تام ولا يحفز إعادة رسم المكون إطلاقاً.
لماذا يفشل تعريف متغير محلي let intervalId = null داخل دالة المكون في إيقاف المؤقت لاحقاً؟
لأن كل إعادة تصيير للمكون تعيد تشغيل الدالة من الصفر فترجع قيمة المتغير المحلي إلى null ويضيع المعرّف.
للحفاظ على نقاء المكونات وتوقع سلوكها، يجب تجنب قراءة أو تعديل ref.current مباشرة أثناء التصيير.
صواب؛ إذ تجري قراءة وتعديل المرجع داخل معالجات الأحداث للحفاظ على نقاء دالة العرض.
متى يجب اختيار خطاف useState بدلاً من خطاف useRef؟
نختار useState دائماً عندما تدخل القيمة في رسم عناصر الواجهة المرئية للمستخدم.
عند تنفيذ السطر countRef.current = 5 داخل معالج نقر onClick، متى تصبح القيمة الجديدة متاحة للقراءة؟
التعديل على خاصية current يتم تزامنياً فوراً في نفس اللحظة ويكون متاحاً في السطر التالي مباشرة.
تعيد React نفس الكائن المرجعي الثابت في الذاكرة عبر جميع مرات إعادة التصيير لنفس نسخة المكون.
صواب؛ تبقى هوية الكائن المرجعي ثابتة تماماً طوال بقاء نسخة المكون مركبة في الشجرة.
لماذا يُعد تعريف متغير خارج دالة المكون في أعلى الملف أسوأ من useRef عند وجود عدة بطاقات مؤقتة؟
لأن المتغير العام في الملف تشترك فيه جميع نسخ المكون فتطمس البطاقات معرّفات مؤقتات بعضها.
في مكون ساعة الإيقاف، ما التوزيع الهندسي الصحيح للمسؤوليات بين useState وuseRef؟
نحفظ الزمن المعروض على الشاشة في useState، ونحفظ معرّف setInterval غير المرئي في useRef.
تضمن كتابة {countRef.current} مباشرة داخل JSX تحديث الرقم على الشاشة فور كل تعديل للمرجع.
خطأ؛ لأن React لا تعيد الرسم عند تعديل المرجع فستبقى الشاشة متجمدة على قيمة قديمة.