انتقل إلى محتوى الدرس
الدرس 32
دورة ReactJS

حفظ القيم المتغيرة دون إعادة تصيير عبر useRefReferencing Mutable Values with useRef

تعلّم كيف يحفظ خطاف useRef القيم المتغيرة بين مرات التصيير دون التسبب في إعادة رسم المكون، مع بناء ساعة إيقاف دقيقة ومقارنة المرجع مع useState.
أقسام الدرس
6
الأمثلة
3
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

عندما يحتاج المكون إلى تذكر بيانات تظهر للمستخدم على الشاشة نعتمد على useState كي تعيد React رسم الواجهة مع كل تحديث. غير أن المكونات تحتاج أحياناً إلى تذكر قيم داخلية خلف الكواليس — مثل معرّف مؤقت نشط أو طابع زمني سابق أو عداد تشخيصي — لا يغير تعديلها شكل العناصر المرسومة إطلاقاً.

هنا توفر مكتبة React خطاف useRef بوصفه منفذاً هندسياً صامتاً (Escape Hatch) يحتفظ بالقيمة بين مرات التصيير المتتالية دون أن يطلب إعادة تصيير المكون عند الكتابة فيه.

HTML
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 يضمن بقاءه سالماً وجاهزاً للإلغاء الفوري.

مخطط يوضح مراحل عمل useRef: إنشاء الحاوية المبدئية وتعديل خاصية current في الأحداث وبقاء القيمة عبر التصييرات دون إعادة رسم
HTML
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.

تتألق المراجع الصامتة كذلك في رصد إيقاع تفاعل المستخدم — مثل قياس الفارق الزمني بالمللي ثانية بين نقرتين متتاليتين أو منع الإرسال المزدوج السريع — دون إرهاق المتصفح بإعادات رسم متلاحقة لتفاصيل داخلية.

HTML
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

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Ref Container حاوية المرجع
كائن JavaScript مستمر الهوية يضم خاصية current قابلة للتعديل تحتفظ بها React طوال بقاء المكون.
للمراجعة
02 Escape Hatch منفذ الخروج الآمن
آلية في React تتيح للمكون حفظ قيم صامتة أو التخاطب مع واجهات المتصفح الأمرية خارج دورة الرسم.
للمراجعة
03 Silent Mutation التعديل الصامت
تحديث قيمة ref.current مباشرة داخل معالج حدث دون التسبب في جدولة إعادة تصيير للمكون.
للمراجعة
04 Interval Handle معرّف المؤقت الدوري
الرقم التعريفي الذي تعيده دالة setInterval ويلزم حفظه في مرجع لإيقاف المؤقت لاحقاً عبر clearInterval.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 API API
Application Programming Interface
واجهات البرمجة المدمجة في المتصفح مثل دوال المؤقتات والزمن التي نتعامل معها داخل دوال الأحداث.
للمراجعة
02 UI UI
User Interface
طبقة العرض المرئية للمستخدم والتي تقودها الحالة والخصائص لا المراجع الصامتة.
للمراجعة
03 ID ID
Identifier
معرّف فريد يمثل مؤقتاً نشطاً في المتصفح لتمكين إلغائه بدقة عند الطلب.
للمراجعة
04 JSX JSX
JavaScript XML
صياغة توصيف الواجهة في React والتي يجب أن تقرأ الحالة والخصائص بنقاء دون قراءة ref.current.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. افتح مثال ساعة الإيقاف في محرر التجريب، وتأكد من عمل الإيقاف عبر intervalRef.current ثم أضف زر تسجيل جولة يعرض أزمنة الجولات في الحالة.

  2. عدّل مثال قياس إيقاع النقر بحيث يعرض تنبيهاً خاصاً عندما يكون الفارق الزمني المحفوظ في المرجع أقل من 300 مللي ثانية.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

10أسئلة 2أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي10 أسئلة تنتظرك
01

ما القيمة الدقيقة التي يعيدها استدعاء useRef(0) داخل المكون؟

يعيد خطاف useRef كائناً ثابت الهوية يحتوي على خاصية واحدة اسمها current مهيأة بالقيمة 0.

02

يؤدي إسناد قيمة جديدة إلى خاصية ref.current إلى جدولة إعادة تصيير للمكون تلقائياً.

خطأ؛ فتعديل خاصية ref.current يتم بصمت تام ولا يحفز إعادة رسم المكون إطلاقاً.

03

لماذا يفشل تعريف متغير محلي let intervalId = null داخل دالة المكون في إيقاف المؤقت لاحقاً؟

لأن كل إعادة تصيير للمكون تعيد تشغيل الدالة من الصفر فترجع قيمة المتغير المحلي إلى null ويضيع المعرّف.

04

للحفاظ على نقاء المكونات وتوقع سلوكها، يجب تجنب قراءة أو تعديل ref.current مباشرة أثناء التصيير.

صواب؛ إذ تجري قراءة وتعديل المرجع داخل معالجات الأحداث للحفاظ على نقاء دالة العرض.

05

متى يجب اختيار خطاف useState بدلاً من خطاف useRef؟

نختار useState دائماً عندما تدخل القيمة في رسم عناصر الواجهة المرئية للمستخدم.

06

عند تنفيذ السطر countRef.current = 5 داخل معالج نقر onClick، متى تصبح القيمة الجديدة متاحة للقراءة؟

التعديل على خاصية current يتم تزامنياً فوراً في نفس اللحظة ويكون متاحاً في السطر التالي مباشرة.

07

تعيد React نفس الكائن المرجعي الثابت في الذاكرة عبر جميع مرات إعادة التصيير لنفس نسخة المكون.

صواب؛ تبقى هوية الكائن المرجعي ثابتة تماماً طوال بقاء نسخة المكون مركبة في الشجرة.

08

لماذا يُعد تعريف متغير خارج دالة المكون في أعلى الملف أسوأ من useRef عند وجود عدة بطاقات مؤقتة؟

لأن المتغير العام في الملف تشترك فيه جميع نسخ المكون فتطمس البطاقات معرّفات مؤقتات بعضها.

09

في مكون ساعة الإيقاف، ما التوزيع الهندسي الصحيح للمسؤوليات بين useState وuseRef؟

نحفظ الزمن المعروض على الشاشة في useState، ونحفظ معرّف setInterval غير المرئي في useRef.

10

تضمن كتابة {countRef.current} مباشرة داخل JSX تحديث الرقم على الشاشة فور كل تعديل للمرجع.

خطأ؛ لأن React لا تعيد الرسم عند تعديل المرجع فستبقى الشاشة متجمدة على قيمة قديمة.