🚀 إتقان useRef: جسرك للوصول إلى عناصر الصفحة في React
حتى الآن، تعلمت أن React تدير الواجهة بناءً على "الحالة" (State)، وعندما تتغير الحالة، يقوم React بتحديث الصفحة تلقائياً.
لكن، هل هناك حالات نحتاج فيها إلى "لمس" عنصر HTML مباشرة؟ أو تخزين قيمة معينة دون أن تتسبب في إعادة تشغيل الرندر (Re-render) للمكون؟ هنا يأتي دور الـ Hook السحري الذي يسمى useRef.
❓ ما هو الـ useRef ببساطة؟
الـ useRef هو عبارة عن "صندوق" أو "مرجع" يمكنك وضع أي قيمة داخله، وهذه القيمة تبقى ثابتة ومحفوظة طوال فترة حياة المكون.
هناك فائدتان أساسيتان لاستخدامه:
- الوصول المباشر لعناصر DOM: مثل التركيز على حقل إدخال (Input Focus)، أو معرفة عرض عنصر معين.
- تخزين قيم متغيرة لا تؤثر على الواجهة: إذا قمت بتغيير قيمة داخل
useRefفإن React لن تعيد بناء المكون (No Re-render)، وهذا يختلف تماماً عنuseState.
🛠️ كيف نستخدم useRef للوصول إلى عناصر HTML؟
تخيل أنك تريد جعل مؤشر الكتابة يظهر تلقائياً في حقل الإدخال (Input) بمجرد الضغط على زر معين. في JavaScript العادية كنت ستستخدم document.getElementById(). أما في React، فالطريقة الاحترافية هي استخدام useRef.
إليك الخطوات بالتفصيل:
- استيراد
useRefمن مكتبة React. - إنشاء مرجع (Ref) باستخدام
useRef(null). - ربط هذا المرجع بالعنصر المطلوب عن طريق خاصية
ref. - الوصول للعنصر عبر الخاصية
.current.
لنطبق ذلك في هذا المثال البسيط:
import React, { useRef } from 'react';
function TextInputFocus() {
// 1. Create a ref initialized to null
const inputElement = useRef(null);
const handleFocusClick = () => {
// 3. Access the DOM element using .current and call focus()
// الوصول إلى العنصر الحقيقي في الصفحة وتنفيذ أمر التركيز
inputElement.current.focus();
};
return (
<div style={{ padding: '20px' }}>
{/* 2. Attach the ref to the input element */}
<input
ref={inputElement}
type="text"
placeholder="Click the button to focus me!"
/>
<br /><br />
<button onClick={handleFocusClick}>
Focus the Input 🎯
</button>
</div>
);
}
export default TextInputFocus;
شرح الكود:
useRef(null): أنشأنا حاوية فارغة في البداية.ref={inputElement}: أخبرنا React "يا ريأكت، اربطي هذا المدخل (Input) بهذا المرجع".inputElement.current: هنا تكمن القوة، فكلمةcurrentهي التي تحتوي على عنصر الـ HTML الفعلي.
📦 استخدام useRef لتخزين قيم (بدون Re-render)
أحياناً نحتاج لتخزين قيمة ما (مثل مؤقت أو رقم معين)، ولكننا لا نريد أن تظهر هذه القيمة في الواجهة، ولا نريد أن يتم تحديث الصفحة كلما تغيرت هذه القيمة.
قارن بين useState و useRef:
- useState: عندما تتغير القيمة ⬅️ يعيد React تشغيل المكون ⬅️ تتحدث الواجهة (UI).
- useRef: عندما تتغير القيمة ⬅️ لا يعيد React تشغيل المكون ⬅️ لا تتحدث الواجهة.
مثال توضيحي:
import React, { useRef, useState } from 'react';
function ClickCounter() {
const [renderCount, setRenderCount] = useState(0); // State causes re-render
const countRef = useRef(0); // Ref does NOT cause re-render
const incrementRef = () => {
countRef.current = countRef.current + 1;
console.log("Ref Value:", countRef.current);
// القيمة تزيد في الخلفية لكن الصفحة لا تتحدث
};
const incrementState = () => {
setRenderCount(renderCount + 1);
// هنا الصفحة ستعيد بناء نفسها وتظهر القيمة الجديدة
};
return (
<div style={{ padding: '20px' }}>
<p>State Count: {renderCount}</p>
<p>Ref Count: {countRef.current} (Won't update on screen until render)</p>
<button onClick={incrementRef}>Increment Ref 🤫</button>
<button onClick={incrementState}>Increment State 📢</button>
</div>
);
}
export default ClickCounter;
⚠️ ملاحظات هامة للمبتدئين
- لا تستخدم
useRefلقراءة قيم من المدخلات (Inputs) إذا كنت تريد عرضها لحظياً على الشاشة؛ في هذه الحالة استخدمuseState(ما يسمى بالـ Controlled Components). - تذكر دائماً أن الوصول للعنصر يكون عن طريق
.current. إذا حاولت الوصول لـinputElementمباشرة بدون.currentفلن يعمل الكود. - استخدم
useRefفقط عندما تحتاج فعلياً للتعامل مع الـ DOM أو تخزين قيم "سرية" لا تؤثر على شكل الصفحة.
🎓 اختبر معلوماتك
التعليقات
شاركنا رأيك أو أسئلتك حول هذا المقال