فهم العرض الشرطي
يسمح لك العرض الشرطي في React بعرض عناصر واجهة مستخدم مختلفة بناءً على شروط معينة. تماماً مثل عبارات JavaScript الشرطية، يمكنك استخدام عبارات if والمعاملات الثلاثية والمعاملات المنطقية للتحكم فيما يتم عرضه.
المفهوم الأساسي: في React، يمكنك إنشاء مكونات أو عناصر مختلفة وعرض فقط تلك التي تحتاجها بناءً على حالة التطبيق. هذا يجعل واجهة المستخدم ديناميكية ومستجيبة لتفاعلات المستخدم وتغييرات البيانات.
استخدام عبارات If/Else
الطريقة الأكثر مباشرة لعرض المكونات بشكل شرطي هي استخدام عبارات JavaScript العادية if/else خارج عبارة return:
function Greeting({ isLoggedIn }) {
if (isLoggedIn) {
return <h1>مرحباً بعودتك!</h1>;
} else {
return <h1>يرجى تسجيل الدخول.</h1>;
}
}
// الاستخدام
function App() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
<button onClick={() => setIsLoggedIn(!isLoggedIn)}>
{isLoggedIn ? 'تسجيل الخروج' : 'تسجيل الدخول'}
</button>
</div>
);
}
المعامل الثلاثي
المعامل الثلاثي (condition ? true : false) مثالي للعرض الشرطي المضمن داخل JSX:
function UserStatus({ isActive }) {
return (
<div>
<h2>حالة المستخدم</h2>
<p>
أنت حالياً{" "}
{isActive ? (
<span style={{ color: 'green' }}>متصل</span>
) : (
<span style={{ color: 'red' }}>غير متصل</span>
)}
</p>
<div className={isActive ? 'status-active' : 'status-inactive'}>
{isActive ? 'متصل' : 'غير متصل'}
</div>
</div>
);
}
أفضل ممارسة: استخدم المعاملات الثلاثية للشروط البسيطة مع حالتي صواب وخطأ. للشروط الأكثر تعقيداً أو عندما تحتاج فقط إلى عرض شيء في حالة واحدة، استخدم معامل && المنطقي بدلاً من ذلك.
معامل AND المنطقي (&&)
معامل && مثالي عندما تريد عرض شيء فقط إذا كان الشرط صحيحاً، وعدم عرض أي شيء بخلاف ذلك:
function Notifications({ messages }) {
return (
<div>
<h2>صندوق الوارد</h2>
{messages.length > 0 && (
<div className="notification-badge">
لديك {messages.length} رسائل غير مقروءة
</div>
)}
{messages.length === 0 && (
<p>لا توجد رسائل جديدة</p>
)}
</div>
);
}
// الاستخدام
function App() {
const [messages, setMessages] = useState(['مرحباً', 'أهلاً']);
return (
<div>
<Notifications messages={messages} />
<button onClick={() => setMessages([])}>
مسح الرسائل
</button>
</div>
);
}
خطأ شائع: كن حذراً مع القيم الخاطئة على الجانب الأيسر من &&. على سبيل المثال، {count && <div>العدد: {count}</div>} سيعرض "0" عندما يكون count يساوي 0. بدلاً من ذلك، استخدم {count > 0 && ...} أو {!!count && ...}.
متغيرات العناصر
يمكنك تخزين العناصر في متغيرات وتضمينها بشكل شرطي في ناتج العرض:
function LoginControl() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
let button;
if (isLoggedIn) {
button = <button onClick={() => setIsLoggedIn(false)}>تسجيل الخروج</button>;
} else {
button = <button onClick={() => setIsLoggedIn(true)}>تسجيل الدخول</button>;
}
let message;
if (isLoggedIn) {
message = <p>لديك حق الوصول إلى الميزات المميزة.</p>;
} else {
message = <p>يرجى تسجيل الدخول للوصول إلى الميزات المميزة.</p>;
}
return (
<div>
<h1>حالة الحساب</h1>
{message}
{button}
</div>
);
}
شروط متعددة مع Switch
للشروط المتعددة، يمكنك استخدام عبارات switch أو إنشاء كائن تعيين:
function StatusMessage({ status }) {
// الطريقة 1: عبارة Switch
const getMessageWithSwitch = () => {
switch(status) {
case 'loading':
return <div className="spinner">جاري التحميل...</div>;
case 'success':
return <div className="success">تم تحميل البيانات بنجاح!</div>;
case 'error':
return <div className="error">فشل تحميل البيانات.</div>;
default:
return <div>لا توجد حالة</div>;
}
};
// الطريقة 2: تعيين الكائن (أنظف)
const statusComponents = {
loading: <div className="spinner">جاري التحميل...</div>,
success: <div className="success">تم تحميل البيانات بنجاح!</div>,
error: <div className="error">فشل تحميل البيانات.</div>,
idle: <div>لا توجد حالة</div>
};
return (
<div>
{/* استخدام switch */}
{getMessageWithSwitch()}
{/* أو استخدام تعيين الكائن */}
{statusComponents[status] || statusComponents.idle}
</div>
);
}
عدم عرض شيء (Null)
في بعض الأحيان تريد أن يخفي المكون نفسه. أرجع null لعدم عرض أي شيء:
function WarningBanner({ warning, onClose }) {
if (!warning) {
return null; // لا تعرض أي شيء
}
return (
<div className="warning-banner">
<span>{warning}</span>
<button onClick={onClose}>×</button>
</div>
);
}
// الاستخدام
function App() {
const [warning, setWarning] = useState('ستنتهي جلستك خلال 5 دقائق');
return (
<div>
<WarningBanner
warning={warning}
onClose={() => setWarning(null)}
/>
<h1>لوحة التحكم</h1>
</div>
);
}
مهم: إرجاع null من مكون لا يؤثر على دوال دورة الحياة. لا يزال المكون يُركب ويُحدث بشكل طبيعي، إنه فقط لا يعرض أي شيء مرئي.
فئات CSS الشرطية
يمكنك تطبيق فئات CSS بشكل شرطي لتغيير مظهر العناصر:
function Button({ isPrimary, isDisabled, children }) {
// الطريقة 1: قوالب حرفية
const className1 = `btn ${isPrimary ? 'btn-primary' : 'btn-secondary'} ${isDisabled ? 'btn-disabled' : ''}`;
// الطريقة 2: ربط المصفوفة
const className2 = [
'btn',
isPrimary ? 'btn-primary' : 'btn-secondary',
isDisabled && 'btn-disabled'
].filter(Boolean).join(' ');
// الطريقة 3: على أساس الكائن (تتطلب مكتبة classnames)
// const className3 = classnames({
// 'btn': true,
// 'btn-primary': isPrimary,
// 'btn-secondary': !isPrimary,
// 'btn-disabled': isDisabled
// });
return (
<button className={className1} disabled={isDisabled}>
{children}
</button>
);
}
// الاستخدام
function App() {
return (
<div>
<Button isPrimary={true} isDisabled={false}>
حفظ
</Button>
<Button isPrimary={false} isDisabled={false}>
إلغاء
</Button>
<Button isPrimary={true} isDisabled={true}>
جاري التحميل...
</Button>
</div>
);
}
مثال على العرض الشرطي المعقد
إليك مثال واقعي يجمع بين تقنيات العرض الشرطي المتعددة:
function UserDashboard({ user, isLoading, error }) {
// عوائد مبكرة للحالات الخاصة
if (isLoading) {
return <div className="loading">جاري تحميل بيانات المستخدم...</div>;
}
if (error) {
return (
<div className="error-container">
<h2>خطأ</h2>
<p>{error.message}</p>
<button onClick={() => window.location.reload()}>
إعادة المحاولة
</button>
</div>
);
}
if (!user) {
return <div>لم يتم العثور على المستخدم</div>;
}
// العرض الرئيسي مع شروط متداخلة
return (
<div className="dashboard">
<h1>مرحباً، {user.name}!</h1>
{/* شارة شرطية */}
{user.isPremium && (
<span className="premium-badge">عضو مميز</span>
)}
{/* محتوى شرطي بناءً على نوع الحساب */}
{user.accountType === 'admin' ? (
<AdminPanel />
) : user.accountType === 'moderator' ? (
<ModeratorPanel />
) : (
<UserPanel />
)}
{/* إشعار شرطي */}
{user.notifications.length > 0 && (
<div className="notifications">
<h3>لديك {user.notifications.length} إشعارات</h3>
{user.notifications.map(notif => (
<div key={notif.id}>{notif.message}</div>
))}
</div>
)}
{/* تحذير شرطي */}
{!user.emailVerified && (
<div className="warning">
يرجى التحقق من عنوان بريدك الإلكتروني
</div>
)}
</div>
);
}
نصيحة للأداء: استخدم عمليات الإرجاع المبكرة للحالات الخاصة (التحميل، الخطأ، عدم وجود بيانات) في أعلى مكونك. هذا يحافظ على منطق العرض الرئيسي نظيفاً وأسهل للفهم.
تمرين 1: قائمة المهام مع المرشحات
أنشئ قائمة مهام مع عرض شرطي لعروض مختلفة:
- عرض أزرار تصفية "الكل" و"نشط" و"مكتمل"
- عرض قوائم مختلفة بناءً على المرشح المحدد
- إذا لم تتطابق أي مهام مع المرشح، اعرض رسالة "لم يتم العثور على مهام"
- عرض عداد: "X مهام نشطة" (فقط إذا كانت هناك مهام نشطة)
- عرض زر "مسح المكتملة" (فقط إذا كانت هناك مهام مكتملة)
- عرض أنماط مختلفة للمهام المكتملة مقابل النشطة
تلميح: استخدم الحالة لتتبع المرشح الحالي واستخدم العرض الشرطي لإظهار المهام المناسبة.
تمرين 2: تدفق المصادقة
ابنِ مكوناً يعرض شاشات مختلفة بناءً على حالة المصادقة:
- عرض دوار التحميل أثناء التحقق من المصادقة
- عرض نموذج تسجيل الدخول إذا لم يتم المصادقة
- عرض لوحة تحكم المستخدم إذا تمت المصادقة
- عرض رسالة خطأ إذا فشلت المصادقة
- في لوحة التحكم، عرض أدوات المسؤول فقط إذا كان المستخدم مسؤولاً
- عرض لافتة ترحيب فقط في أول تسجيل دخول (تتبع بالحالة)
إضافي: أضف مربع اختيار "تذكرني" يعرض بشكل شرطي في نموذج تسجيل الدخول.
تمرين 3: بطاقة منتج مع ميزات شرطية
أنشئ مكون بطاقة منتج بعناصر شرطية متنوعة:
- عرض شارة "تخفيض" إذا كان المنتج يحتوي على خصم
- عرض السعر الأصلي (مشطوب) وسعر البيع إذا كان معروضاً للبيع
- عرض رسالة "نفذت الكمية" إذا كانت الكمية 0
- تعطيل زر "أضف إلى السلة" إذا نفذت الكمية
- عرض تقييم النجوم فقط إذا كان للمنتج مراجعات
- عرض شارة "جديد" إذا تمت إضافة المنتج خلال آخر 7 أيام
- تطبيق فئات CSS مختلفة بناءً على فئة المنتج
تلميح: مرر كائن منتج بخصائص مثل price و salePrice و quantity و rating و createdAt و category.