التقنيات المتقدمة لمعالجة النماذج (Advanced Form Handling & Dynamic Validation)
| المحور الهندسي | المعالجة اليدوية التقليدية | المعالجة بالمكتبات المتخصصة (مثل Formik / React Hook Form) |
|---|---|---|
| إدارة حالة الحقول State | إنشاء كائن حالة أو حالات منفصلة تتحدث مع كل ضغطة كيبورد | تقليل عمليات الرندرة عبر ربط الحقول بشكل غير موجه وفعال |
| التحقق من البيانات Validation | كتابة دوال شروط يدوية مقترنة بحدث التسليم أو التغيير | استخدام مخططات جاهزة وصارمة مثل Yup أو Zod بأسلوب نظيف |
| إدارة أخطاء الحقول Errors | حفظ كائن أخطاء يدوي وتعديله عند اكتشاف أي مخالفة | تتبع أخطاء كل حقل لحظياً تلقائياً مع تسهيل إظهار الرسائل |
| كفاءة الأداء وتجربة المستخدم | قد يسبب بطء في النماذج الضخمة جداً بسبب كثرة الرندرة | أداء عالي وسرعة استجابة فائقة حتى مع ملايين المدخلات |
بناء النماذج المعقدة (مثل نماذج التسجيل، إنشاء الكورسات، أو الدفع) يتطلب ما هو أكثر من مجرد التقاط قيم المدخلات. تحتاج الواجهة إلى:
تعد تجربة المستخدم (UX) سيئة جداً إذا أظهرت له رسالة "البريد الإلكتروني مطلوب" فور فتح الصفحة وقبل أن يبدأ في الكتابة! الحل الهندسي هو تتبع الحقول التي قام المستخدم بالتفاعل معها وتركها عبر حدث onBlur:
| 1 | import { useState } from 'react'; |
| 2 | |
| 3 | function AdvancedForm() { |
| 4 | const [email, setEmail] = useState(''); |
| 5 | const [touched, setTouched] = useState(false); // هل تم لمس الحقل؟ |
| 6 | |
| 7 | // يكون الخطأ فعالاً فقط إذا لمس المستخدم الحقل وكانت القيمة غير صالحة |
| 8 | const isError = touched && !email.includes('@'); |
| 9 | |
| 10 | return ( |
| 11 | <div> |
| 12 | <input |
| 13 | type="email" |
| 14 | value={email} |
| 15 | onChange={(e) => setEmail(e.target.value)} |
| 16 | onBlur={() => setTouched(true)} // تحديد أن الحقل تم تفاعله |
| 17 | style={{ borderColor: isError ? 'red' : '#ccc' }} |
| 18 | /> |
| 19 | {isError && <span style={{ color: 'red' }}>البريد الإلكتروني غير صحيح!</span>} |
| 20 | </div> |
| 21 | ); |
| 22 | } |
بدلاً من كتابة شروط متفرقة، ننشئ دالة تدقيق ترجع كائناً بحالة الأخطاء لكل حقل:
| 1 | function CourseCreateForm() { |
| 2 | const [formData, setFormData] = useState({ title: '', price: '' }); |
| 3 | const [errors, setErrors] = useState({}); |
| 4 | |
| 5 | // دالة الفحص المركبة |
| 6 | const validate = (data) => { |
| 7 | const errs = {}; |
| 8 | if (!data.title.trim()) errs.title = 'عنوان الكورس مطلوب'; |
| 9 | if (!data.price || data.price <= 0) errs.price = 'السعر يجب أن يكون أكبر من 0'; |
| 10 | return errs; |
| 11 | }; |
| 12 | |
| 13 | const handleSubmit = (e) => { |
| 14 | e.preventDefault(); |
| 15 | const validationErrors = validate(formData); |
| 16 | |
| 17 | if (Object.keys(validationErrors).length > 0) { |
| 18 | setErrors(validationErrors); // توقيف الإرسال وعرض الأخطاء |
| 19 | } else { |
| 20 | setErrors({}); |
| 21 | console.log('تم إرسال البيانات بنجاح:', formData); |
| 22 | } |
| 23 | }; |
| 24 | |
| 25 | return ( |
| 26 | <form onSubmit={handleSubmit}> |
| 27 | <input |
| 28 | name="title" |
| 29 | onChange={(e) => setFormData({ ...formData, title: e.target.value })} |
| 30 | placeholder="عنوان الكورس" |
| 31 | /> |
| 32 | {errors.title && <p>{errors.title}</p>} |
| 33 | |
| 34 | <button type="submit">حفظ الكورس</button> |
| 35 | </form> |
| 36 | ); |
| 37 | } |
في بعض الأحيان يحتاج المستخدم لإضافة أكثر من حقل بشكل ديناميكي (مثل إضافة متطلبات الكورس):
ℹ️ معلومة
إذا كان النموذج يحتوي على أكثر من 5 حقول وبدأت تشعر بشرود الكود وتضخم الـ State ودواريخ الـ Validation: لا تعِد اختراع العجلة! استخدم مكتبة React Hook Form المعتمدة عالمياً.