في هذا الدرس 6تصفّح المواضيع
عندما يتوسع نموذج التسجيل أو الدفع ليضم خمسة أو عشرة حقول، يصبح تعريف عشرة متغيرات useState() منفصلة وعشر دوال معالجة متشابهة عبئاً يضعف مقروئية المكون. الحل الهندسي النظيف هو جمع حقول النموذج المترابطة في كائن حالة واحد.
امنح كل حقل خاصية name مطابقة لمفتاحه في الكائن، واستخدم معالج تغيير موحداً يعتمد خاصية المفتاح المحسوب: setForm((prev) => ({ ...prev, [name]: nextValue })).
function handleChange(e) {
const { name, type, value, checked } = e.target;
setForm((prev) => ({
...prev,
[name]: type === 'checkbox' ? checked : value,
}));
}
يُعد إظهار رسائل الخطأ الحمراء في وجه المستخدم قبل أن يلمس الحقل — أو وهو لا يزال في منتصف كتابة بريده الإلكتروني — تجربة مزعجة للغاية. يطبق مهندسو الواجهات المحترفون قاعدة «تأجيل التنبيه، والتبرئة الفورية».
تتبع حالة لمس الحقول في كائن touched عند انطلاق حدث مغادرة الحقل onBlur (أو عند محاولة الإرسال)، فلا تعرض رسالة الخطأ إلا للحقل الذي غادره المستخدم فعلاً، وأخفِها لحظياً فور تصحيحه للإدخال.
const [email, setEmail] = useState('');
const [touched, setTouched] = useState(false);
const isInvalid = !email.includes('@');
const showError = touched && isInvalid;
اكتب قواعد الفحص داخل دالة نقية مساعدة validateForm(values) تفحص قيم الكائن الحالي وتعيد كائن أخطاء يربط اسم كل حقل برسالة إرشادية واضحة قابلة للتنفيذ، مثل تحديد الحد الأدنى لطول كلمة المرور بدلاً من عبارة غامضة.
ولأن التحقق المحلي فوري وحتمي، استدعِ const errors = validateForm(form) مباشرة أثناء التصيير بدلاً من تخزين الأخطاء في متغير حالة إضافي قد ينفصل عن القيم الفعلية.
function validateSignup(values) {
const errors = {};
if (values.username.trim().length < 3) {
errors.username = 'Minimum 3 characters required.';
}
if (values.password.length < 8) {
errors.password = 'Use 8 or more characters.';
}
return errors;
}
الاعتماد على اللون الأحمر وحده لتمييز الحقل الخاطئ لا يظهر لمستخدمي قارئات الشاشة المكفوفين ولا لمن يعانون ضعف تمييز الألوان. يتطلب التحقق المتاح قياسياً ربط سمتين من معيار WAI-ARIA بمعرّف مولد عبر useId():
- سمة
aria-invalidلإبلاغ التقنيات المساعدة بأن الحقل الحالي يحوي خطأً. - سمة
aria-describedbyمربوطة بمعرّف فقرة رسالة الخطأ حتى تُقرأ إرشادات التصحيح صوتياً تلقائياً.
<input
id={fieldId}
aria-invalid={showErr}
aria-describedby={showErr ? errId : undefined}
value={slug}
onChange={(e) => setSlug(e.target.value)}
/>
{showErr && <p id={errId} role="alert">{errMsg}</p>}
لا تحتاج كل النماذج إلى تتبع كل حرف في الحالة؛ فعندما يقتصر الغرض من نموذج بسيط على قراءة القيم لحظة الإرسال فقط دون عدادات حية أو شروط فورية، يمكنك قراءة الحقول مباشرة عبر واجهة FormData القياسية في المتصفح.
مرر العنصر e.currentTarget إلى new FormData(e.currentTarget) وحوّل المدخلات إلى كائن نظيف عبر Object.fromEntries() اعتماداً على خاصية name لكل حقل.
function handleFeedbackSubmit(e) {
e.preventDefault();
const fd = new FormData(e.currentTarget);
const payload = Object.fromEntries(fd.entries());
setSubmittedData(payload);
e.currentTarget.reset();
}
ثمة قاعدة هندسية وأمنية حاسمة لا تقبل التهاون في أي تطبيق حقيقي وهي أن التحقق داخل مكونات React يهدف لتحسين تجربة المستخدم فقط، ولا يُعد حماية أمنية مطلقاً؛ إذ يمكن لأي شخص تجاوز المتصفح وإرسال طلبات HTTP مباشرة إلى الخادم.
لذلك يجب تطبيق جميع قواعد التحقق والصلاحيات وفحص تكرار البريد وتنظيف البيانات على الخادم الخلفي إلزامياً، مع عرض أي أخطاء يعيدها الخادم بوضوح في واجهة النموذج. يوضح الجدول التالي تكامل الطبقتين:
| بُعد المقارنة | تحقق الواجهة في React | التحقق الخلفي في الخادم |
|---|---|---|
| الهدف الأساسي | إرشاد لحظي سريع يجنب المستخدم انتظار الشبكة | حماية أمنية إلزامية وضمان سلامة قاعدة البيانات |
| إمكانية التجاوز | نعم عبر أدوات المطور أو إرسال طلب مباشر | لا يمكن تجاوزه لأنه يعمل في بيئة الخادم الموثوقة |
| أمثلة الفحوصات | الحقول الفارغة وطول النص وصيغة البريد | الصلاحيات وعدم تكرار السجلات وتطهير المدخلات |
| توقيت التنفيذ | أثناء الكتابة وعند مغادرة الحقل وقبل الإرسال | عند استلام كل طلب تعديل أو إنشاء وارد للخادم |
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
جمعت في هذا الدرس حقول النماذج المتعددة في كائن حالة موحد، وضبطت توقيت رسائل الخطأ بحدث onBlur وتتبع اللمس، وربطت سمات الإتاحة لقارئات الشاشة، واستخدمت FormData للنماذج البسيطة مع ترسيخ الفارق بين تحقق الواجهة وأمان الخادم. الخطوة التالية: انتقل الآن إلى الدرس رقم 25 «تصميم هيكل الحالة وحساب القيم المشتقة» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Computed Property Name اسم الخاصية المحسوب
- صياغة كائنات حديثة [name]: value تتيح تحديث المفتاح المطابق لاسم الحقل ديناميكياً داخل الحالة.
- للمراجعة
- 02 Touched State حالة لمس الحقل
- تتبع ما إذا كان المستخدم قد تفاعل مع الحقل وغادره عبر onBlur لمنع ظهور رسائل الخطأ قبل أوانها.
- للمراجعة
- 03 Accessible Error Binding ربط الخطأ المتاح صوتياً
- الجمع بين سمتي aria-invalid وaria-describedby لتمكين قارئات الشاشة من نطق حالة الخطأ وسببه.
- للمراجعة
- 04 FormData API واجهة FormData
- كائن متصفح قياسي يستخرج قيم الحقول المسماة مباشرة من عنصر النموذج لحظة الإرسال.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 ARIA ARIA
- Accessible Rich Internet Applications
- سمات قياسية عالمية تنقل حالات التحقق والأخطاء التفاعلية بوضوح إلى التقنيات المساعدة.
- للمراجعة
- 02 UX UX
- User Experience
- جودة وسلاسة تجربة المستخدم أثناء تعبئة النموذج وتلقي الإرشادات التصحيحية.
- للمراجعة
- 03 WCAG WCAG
- Web Content Accessibility Guidelines
- إرشادات إتاحة محتوى الويب العالمية التي تشترط عدم الاكتفاء باللون وحده للإشارة إلى الأخطاء.
- للمراجعة
- 04 HTTP HTTP
- Hypertext Transfer Protocol
- بروتوكول الشبكة الذي يمكن عبره إرسال طلبات مباشرة للخادم متجاوزة فحوصات المتصفح.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
افتح مثال UnifiedAccountForm وأضف خاصية jobTitle للكائن مع حقل إدخال يحمل نفس خاصية name مستخدماً نفس دالة التغيير الموحدة.
-
افتح مثال AccessibleSlugInput وأدخل مسافات أو أحرفاً كبيرة لملاحظة رسالة التنبيه ثم صححها بشرطات لمراقبة تحول الحالة إلى صالحة.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي10 أسئلة تنتظرك +
ما الصياغة الحديثة التي تتيح لدالة تغيير واحدة تحديث الحقل المطابق لخاصية e.target.name داخل كائن الحالة؟
تسمح أسماء الخصائص المحسوبة بتحديث المفتاح الموافق لاسم الحقل ديناميكياً مع الحفاظ على بقية الحقول.
أي حدث في React يُستخدم عادةً لتسجيل أن المستخدم قد غادر الحقل لتفعيل التحقق المهذب؟
ينطلق حدث onBlur فور انتقال التركيز خارج الحقل مما يجعله مثالياً لتسجيل لمس الحقل.
يمكن حساب رسائل التحقق المتزامنة مباشرة أثناء التصيير من حالة النموذج الحالية دون الحاجة لتخزين متغير حالة مكرر للأخطاء.
صواب؛ حساب الأخطاء مباشرة أثناء التصيير يمنع أي تضارب بين القيم الحالية ورسائل الخطأ.
أي زوج من سمات الإتاحة يربط الحقل غير الصالح برسالة الخطأ المرئية ليقرأها قارئ الشاشة؟
تعلن aria-invalid وجود الخطأ بينما تشير aria-describedby إلى معرّف فقرة التوضيح.
إضافة تحقق شامل ودقيق داخل مكون النموذج في React يغني تماماً عن التحقق من البيانات في الخادم الخلفي.
خطأ؛ يمكن تجاوز فحوصات المتصفح بسهولة عبر طلبات الشبكة المباشرة لذا يظل تحقق الخادم إلزامياً للأمان.
عند استخراج بيانات نموذج بسيط عبر new FormData(e.currentTarget)، ما السمة الواجب توفرها على كل حقل؟
يجمع كائن FormData القيم اعتماداً على سمة الاسم name الموضوعة على كل عنصر نموذج.
داخل دالة التغيير الموحدة التي تعالج الحقول النصية وخانات الاختيار معاً، كيف نختار القيمة الصحيحة؟
نفحص نوع الحقل فإذا كان checkbox نأخذ checked وإلا نأخذ value.
يكفي تلوين إطار الحقل باللون الأحمر دون نص توضيحي أو سمات ARIA لتحقيق إتاحة كاملة للنموذج.
خطأ؛ اللون وحده لا يظهر لمستخدمي قارئات الشاشة ولا يحقق معايير الإتاحة العالمية.
ماذا يعني مبدأ تجربة المستخدم «تأجيل التنبيه والتبرئة الفورية» في النماذج التفاعلية؟
انتظار مغادرة الحقل أو الإرسال قبل إظهار الخطأ ثم إخفاؤه فوراً بمجرد أن يصبح الإدخال صحيحاً.
متى يكون استخدام الحالة المحكومة useState أفضل من الاكتفاء بقراءة FormData عند الإرسال؟
كلما تطلبت الواجهة تفاعلاً لحظياً مع كل حرف مثل عدادات الأحرف وقوائم شروط كلمة المرور الحية.