إدارة مدخلات النماذج والنمط الموجه (Controlled vs Uncontrolled Components)
| المجهر التقني | المكونات الموجهة Controlled Components | المكونات غير الموجهة Uncontrolled Components |
|---|---|---|
| مالك البيانات والـ State | جافا سكريبت عبر React State (مصدر الحقيقة الموحد) | شجرة المتصفح المباشرة DOM (عبر الـ Ref) |
| تحديث القيمة لحظياً | يتم مع كل ضربة زر على الكيبورد عبر حدث onChange | لا يتم تحديث القيمة برمجياً إلا عند الاستعلام عنها يدوياً |
| التحقق والفلترة اللحظية Validation | ممتازة وسلسة للغاية (مثل إظهار قوة كلمة المرور أثناء الكتابة) | معقدة وصعبة وتتطلب القراءة اليدوية بعد الانتهاء |
| التوظيف الأمثل في المنصة | النماذج التفاعلية المعقدة وتدقيق البيانات لحظياً | النماذج البسيطة جداً أو رفع الملفات الكبيرة لتوفير الرندرة |
التعامل مع حقول المدخلات (<input>, <textarea>, <select>) في React يحمل فلسفة خاصة. في الويب التقليدي، كان عنصر الـ HTML هو المسعف الأصلي الذي يحتفظ بقيمته بنفسه داخل شجرة الـ DOM.
أما في React، فهناك نمطان هندسيان لإدارة هذه البيانات:
في هذا النمط، نجعل React هي المتحكم الوحيد والكامل في القيمة القادمة والمكتوبة داخل الحقل. نربط خاصيتين أساسيتين بالحقل:
| 1 | function ControlledInput() { |
| 2 | const [email, setEmail] = useState(''); |
| 3 | |
| 4 | return ( |
| 5 | <input |
| 6 | type="email" |
| 7 | value={email} // القيمة مجبورة أن تكون مطابقة للـ State |
| 8 | onChange={(e) => setEmail(e.target.value)} // تحديث الحالة مع كل حرف |
| 9 | /> |
| 10 | ); |
| 11 | } |
لأنه يعطيك التحكم المباشر لحظة بلحظة. يمكنك تعطيل زر الإرسال إذا كان الإيميل غير صحيح، أو تحويل الحروف المكتوبة إلى حروف كبيرة (Uppercase) في نفس لحظة الكتابة!
هنا نترك حقل HTML يحفظ القيمة بنفسه داخل الـ DOM دون إزعاج React بإعادة الرندرة مع كل حرف. وعندما يضغط المستخدم على زر الإرسال، نذهب ونجلب القيمة من المتصفح باستخدام useRef.
| 1 | function UncontrolledInput() { |
| 2 | const emailRef = useRef(); |
| 3 | |
| 4 | const handleSubmit = (e) => { |
| 5 | e.preventDefault(); |
| 6 | // جلب القيمة مباشرة من الـ DOM عند الضغط على الزر فقط |
| 7 | console.log(emailRef.current.value); |
| 8 | }; |
| 9 | |
| 10 | return ( |
| 11 | <form onSubmit={handleSubmit}> |
| 12 | <input type="email" ref={emailRef} /> |
| 13 | <button type="submit">إرسال</button> |
| 14 | </form> |
| 15 | ); |
| 16 | } |
بدلاً من إنشاء useState مستقل لكل حقل في النماذج الكبيرة (مثل اسم المستخدم، البريد، كلمة المرور)، نستخدم كائناً واحداً ينظم العملية بناءً على سمة name الخاصة بالحقل:
إذا كتبت القيمة الابتدائية للـ State كـ undefined أو نسيت وضع قيمة ابتدائية:
| 1 | const [text, setText] = useState(); // ❌ القيمة الابتدائية هنا undefined! |
ستفاجأ بتحذير مزعج من React في الـ Console يقول:
⚠️ تحذير
Warning: A component is changing an uncontrolled input to be controlled.