في هذا الدرس 6تصفّح المواضيع
لا تترك الواجهات الاحترافية في React المستخدم في حيرة أمام مساحة بيضاء صامتة يتساءل فيها هل لا يزال التحميل جارياً أم تعطل الخادم أم لا توجد نتائج أصلاً. تتطلب كل شاشة تعتمد على بيانات الشبكة تصميم أربع حالات بصرية مستقلة بوضوح:
- حالة التحميل (Loading): تظهر فور انطلاق الطلب لطمأنة المستخدم بأن الجلب جارٍ.
- حالة الخطأ (Error): تظهر عند انقطاع الاتصال أو فشل
response.okمع إتاحة خيار الاستعادة. - حالة الفراغ (Empty): تظهر عندما ينجح الطلب برمز
200 OKلكن المصفوفة خاليةitems.length === 0. - حالة النجاح (Success): تعرض البطاقات أو الجداول الفعلية عند توفر سجل واحد على الأقل.
if (status === 'loading') {
return <p aria-busy="true">Loading...</p>;
}
if (status === 'error') {
return <p role="alert">{errorMsg}</p>;
}
if (courses.length === 0) {
return <p>No matching courses found.</p>;
}
return <CourseList items={courses} />;
تؤدي أيقونات الدوران الصغيرة غير المحجوزة المساحة إلى قفز الفقرات والأزرار لأسفل فور وصول البيانات، مما يضر باستقرار التخطيط البصري. يُفضل دائماً رسم بطاقات هيكلية هادئة (Skeleton Placeholders) تحجز ارتفاعاً قريباً من البطاقات الفعلية.
ولتحقيق معايير الوصول الشامل، أضف السمتين aria-busy="true" وaria-live="polite" إلى حاوية الانتظار حتى تُعلم قارئات الشاشة المستخدم باكتمال التحميل بهدوء ودون مقاطعة.
إجبار المستخدم على تحديث تبويب المتصفح بالكامل عند حدوث تقطع عابر في الشبكة يضيع مدخلاته وموضع التمرير في الصفحة. توفر إضافة زر إعادة المحاولة داخل بطاقة الخطأ إمكانية استعادة البيانات موضعياً وبسلاسة.
ومن أنظف الأنماط التصريحية لربط زر الإعادة مع useEffect() تعريف عداد بسيط const [retryCount, setRetryCount] = useState(0) ضمن مصفوفة الاعتماديات وزيادته عبر setRetryCount((n) => n + 1) عند النقر.
const [retryTick, setRetryTick] = useState(0);
useEffect(() => {
loadTasks();
}, [retryTick]);
function handleRetry() {
setRetryTick((n) => n + 1);
}
وصول مصفوفة خالية مع رمز 200 OK يعني نجاح الاستعلام برمجياً مع عدم تطابق أي سجل، وليس عطلاً في الشبكة. ميّز دائماً بين حالتين شائعتين للفراغ: حساب جديد لم يُضف فيه أي عنصر بعد (اعرض دعوة لإضافة العنصر الأول)، أو بحث دقيق لم يطابق نتائج (اعرض كلمة البحث الحالية مع زر فوري لمسح التصفية).
if (status === 'success' && items.length === 0) {
return (
<div className="empty-card">
<p>No hardware matches "{search}".</p>
<button onClick={() => setSearch('')}>
Show All
</button>
</div>
);
}
كثيراً ما يؤدي تتبع متغيرات منطقية منفصلة مثل isLoading وisError إلى حالات متناقضة في الواجهة، كنسيان تصفير الخطأ عند الإعادة فيظهر شريط التحميل فوق رسالة الفشل في آن واحد! استبدال الرايات المنفصلة بمتغير نصي موحد status يأخذ إحدى القيم 'loading' | 'error' | 'success' يضمن استحالة تداخل الشاشات. يلخص الجدول التالي تصميم كل حالة:
| حالة الواجهة | الشرط البرمجي الدقيق | متطلبات الوصول وتجربة المستخدم |
|---|---|---|
| التحميل الجاري | status === 'loading' | هيكل حجز مساحة ثابت مع السمة aria-busy="true" |
| فشل الجلب | status === 'error' | رسالة آمنة خالية من التفاصيل الداخلية مع role="alert" وزر إعادة |
| القائمة الفارغة | status === 'success' && items.length === 0 | بطاقة إرشادية محايدة مع زر مسح البحث أو إضافة عنصر |
| عرض السجلات | status === 'success' && items.length > 0 | قائمة دلالية منظمة بمفاتيح item.id المستقرة |
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
تعلّمت في هذا الدرس هندسة الواجهات غير المتزامنة بحالاتها الأربع المتكاملة عبر هياكل التحميل المتاحة بـ aria-busy، ورسائل الخطأ الآمنة المزودة بزر إعادة المحاولة، ومعالجة القوائم الفارغة بمرونة عبر متغير الحالة الموحد status. الخطوة التالية: انتقل الآن إلى الدرس رقم 39 «إلغاء الطلبات ومنع تضارب الاستجابات بـ AbortController» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Skeleton Loader هيكل التحميل التمهيدي
- إطار تمهيدي هادئ يحجز أبعاد البطاقة المتوقعة لمنع قفز التخطيط البصري أثناء انتظار البيانات.
- للمراجعة
- 02 Empty State حالة الفراغ الإرشادية
- واجهة مخصصة تظهر عند نجاح الطلب دون وجود سجلات مطابقة لتوجيه المستخدم لمسح الفلتر أو الإنشاء.
- للمراجعة
- 03 Impossible State الحالة المتناقضة
- خلل برمجي ينشأ عن تعدد المتغيرات المنطقية فيسمح بظهور حالتين متعارضتين كالتحميل والخطأ في وقت واحد.
- للمراجعة
- 04 In-Place Retry إعادة المحاولة الموضعية
- إعادة إطلاق طلب الشبكة الفاشل من داخل المكون نفسه دون إجبار المستخدم على تحديث الصفحة كاملة.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 ARIA ARIA
- Accessible Rich Internet Applications
- مجموعة سمات قياسية مثل aria-busy تبلّغ التقنيات المساعدة وقارئات الشاشة بالتحديثات الحية.
- للمراجعة
- 02 CLS CLS
- Cumulative Layout Shift
- مقياس استقرار بصري يرصد مقدار الإزاحة المفاجئة لعناصر الصفحة أثناء وصول المحتوى غير المتزامن.
- للمراجعة
- 03 UX UX
- User Experience
- جودة التفاعل والوضوح والاطمئنان الذي يختبره المستخدم عبر كافة مراحل التحميل والاستجابة.
- للمراجعة
- 04 CTA CTA
- Call To Action
- زر إجراء واضح ومباشر مثل «أعد المحاولة» أو «مسح البحث» داخل شاشة الخطأ أو الفراغ.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
افتح مثال AsyncCourseExplorer في محرر التجريب وجرّب بحثاً مطابقاً وبحثاً بلا نتائج وزر محاكاة 503 للتحقق من الحالات الأربع.
-
افتح مثال ResilientTaskBoard في محرر التجريب واضغط Retry Now لملاحظة كيف يعيد عداد المحاولة تشغيل التأثير واسترجاع المهام.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي10 أسئلة تنتظرك +
ما الحالات البصرية الأربع الأساسية لأي شاشة تجلب بيانات غير متزامنة في الواجهة؟
تغطي الشاشة المتكاملة أربع حالات: التحميل والخطأ والقائمة الفارغة وعرض البيانات.
أي سمة وصول قياسية تُعلم قارئات الشاشة بأن القسم الحالي قيد التحميل وتحديث محتواه؟
تُشعر السمة aria-busy="true" قارئات الشاشة بأن المنطقة لا تزال تستكمل تحميل عناصرها.
حجز ارتفاع تقريبي عبر هياكل التحميل التمهيدية يمنع القفز المفاجئ لعناصر الصفحة عند وصول البيانات.
صواب؛ فحجز المساحة يحافظ على الثبات البصري ويمنع إزاحة الأزرار والفقرات.
ماذا ينبغي أن تعرض بطاقة الخطأ للمستخدم النهائي عند رد الخادم برمز العطل 503؟
تعرض رسالة واضحة ومطمئنة مع زر إعادة المحاولة دون كشف تفاصيل برمجية داخلية حساسة.
كيف يؤدي زيادة عداد الحالة retryTick بمقدار 1 إلى إعادة تشغيل طلب الشبكة بنظافة؟
بإدراج retryTick في مصفوفة اعتماديات useEffect تعيد React تشغيل دالة الجلب تلقائياً عند تغير قيمته.
عندما يرد الخادم برمز 200 OK مع مصفوفة فارغة []، يجب التعامل معها كحالة قائمة فارغة وليست خطأً في الشبكة.
صواب؛ فعدم وجود نتائج مطابقة استجابة صحيحة تتطلب إرشاداً هادئاً لا رسالة عطل.
ما الإجراء الأكثر فائدة للمستخدم داخل بطاقة القائمة الفارغة الناتجة عن تصفية بحث ضيقة؟
إتاحة زر فوري لمسح الفلتر يعيد نص البحث إلى سلسلة فارغة ليستعيد المستخدم كافة العناصر.
لماذا يُعد متغير الحالة النصي الموحد status أكثر أماناً من فصل متغيري isLoading وisError؟
لأنه يمنع نشوء حالات متناقضة مستحيلة مثل تفعيل التحميل والخطأ في اللحظة ذاتها.
إعادة ضبط status إلى "loading" فور نقر زر المحاولة يمنح المستخدم تأكيداً بصرياً فورياً باستجابة الزر.
صواب؛ فتحويل الحالة فوراً إلى التحميل يزيل رسالة الخطأ السابقة ريثما يكتمل الطلب الجديد.
أي دور قياسي في سمات الوصول يجعل قارئات الشاشة تعلن رسالة الخطأ فور ظهورها للمستخدم؟
ينشئ الدور role="alert" منطقة تنبيه حية تُعلن رسائل الفشل المهمة فور عرضها.