ما هو JSX؟
JSX (JavaScript XML) هو امتداد صيغة لـ JavaScript يتيح لك كتابة كود شبيه بـ HTML في ملفات JavaScript الخاصة بك. تم إنشاؤه بواسطة فريق React لجعل إنشاء عناصر React أكثر سهولة وقابلية للقراءة.
JSX ليس HTML: على الرغم من أن JSX يبدو مشابهاً لـ HTML، إلا أنه في الواقع JavaScript في الأساس. عندما يتم تشغيل الكود، يتم تحويل JSX إلى استدعاءات دوال JavaScript عادية. فهم هذا التمييز أمر بالغ الأهمية لإتقان React.
إليك مثال بسيط يقارن JSX مع JavaScript العادي:
// صيغة JSX (ما تكتبه)
const element = <h1 className="greeting">مرحباً بالعالم!</h1>;
// ما يتم تجميعه (JavaScript نقي)
const element = React.createElement(
'h1',
{ className: 'greeting' },
'مرحباً بالعالم!'
);
نسخة JSX أكثر قابلية للقراءة بكثير وتبدو مثل HTML الذي تعرفه بالفعل. هذا هو السبب في أن مطوري React يفضلون JSX بشكل ساحق على JavaScript العادي.
قواعد صيغة JSX
لدى JSX قواعد محددة يجب عليك اتباعها. لنستكشف كل واحدة:
1. يجب إغلاق جميع العناصر
في HTML، بعض الوسوم مثل <img> و <br> لا تتطلب وسوم إغلاق. في JSX، يجب إغلاق جميع الوسوم:
// ❌ خطأ - أسلوب HTML
<img src="photo.jpg">
<br>
<input type="text">
// ✅ صحيح - أسلوب JSX
<img src="photo.jpg" />
<br />
<input type="text" />
2. استخدم className بدلاً من class
نظراً لأن "class" كلمة محجوزة في JavaScript، تستخدم JSX className لفئات CSS:
// ❌ خطأ
<div class="container">المحتوى</div>
// ✅ صحيح
<div className="container">المحتوى</div>
3. استخدم htmlFor بدلاً من for
وبالمثل، "for" كلمة محجوزة في JavaScript، لذا استخدم htmlFor في العلامات:
// ❌ خطأ
<label for="username">اسم المستخدم:</label>
// ✅ صحيح
<label htmlFor="username">اسم المستخدم:</label>
4. camelCase للسمات
تستخدم JSX تسمية camelCase للسمات التي ستكون مفصولة بشرطة في HTML:
// سمات HTML ← سمات JSX
onclick → onClick
onchange → onChange
tabindex → tabIndex
maxlength → maxLength
autocomplete → autoComplete
5. يجب إرجاع عنصر أصلي واحد
يجب أن تحتوي تعبيرات JSX على عنصر جذر واحد بالضبط. لا يمكنك إرجاع عناصر متعددة دون تغليفها:
// ❌ خطأ - عناصر جذر متعددة
function App() {
return (
<h1>مرحباً</h1>
<p>أهلاً</p>
);
}
// ✅ صحيح - ملفوف في أصل واحد
function App() {
return (
<div>
<h1>مرحباً</h1>
<p>أهلاً</p>
</div>
);
}
React Fragments: إذا كنت لا تريد إضافة غلاف <div> إضافي، استخدم React Fragments: <React.Fragment> أو الاختصار <>. سنغطي هذا لاحقاً في هذا الدرس!
تضمين تعبيرات JavaScript
إحدى أقوى ميزات JSX هي القدرة على تضمين تعبيرات JavaScript باستخدام الأقواس المعقوفة {}:
function Greeting() {
const name = 'سارة';
const age = 25;
return (
<div>
<h1>مرحباً، {name}!</h1>
<p>عمرك {age} سنة.</p>
<p>العام القادم ستكون {age + 1}.</p>
</div>
);
}
ما الذي يمكن وضعه داخل الأقواس المعقوفة؟
- المتغيرات:
{userName}
- التعبيرات:
{2 + 2}، {price * quantity}
- استدعاءات الدوال:
{formatDate(today)}
- عوامل ثلاثية:
{isLoggedIn ? 'تسجيل خروج' : 'تسجيل دخول'}
- طرق المصفوفة:
{items.map(item => item.name)}
function ProductCard() {
const product = {
name: 'لابتوب',
price: 999,
inStock: true
};
const tax = 0.1;
const totalPrice = product.price + (product.price * tax);
return (
<div className="product">
<h2>{product.name}</h2>
<p>السعر: ${product.price}</p>
<p>الإجمالي مع الضريبة: ${totalPrice.toFixed(2)}</p>
<p>الحالة: {product.inStock ? 'متوفر' : 'غير متوفر'}</p>
</div>
);
}
ما لا يمكنك استخدامه في تعبيرات JSX:
- العبارات (if/else، for loops، while loops)
- تصريحات المتغيرات (let، const، var)
- تعريفات الدوال
استخدم التعبيرات فقط! للعرض الشرطي، استخدم عوامل ثلاثية أو AND المنطقي (&&).
سمات JSX والخصائص
يمكنك تمرير السمات إلى عناصر JSX تماماً مثل HTML، ولكن باستخدام camelCase والتعبيرات:
function UserProfile() {
const imageUrl = 'https://example.com/avatar.jpg';
const altText = 'صورة المستخدم';
const isActive = true;
return (
<div>
{/* سمات النصوص تستخدم علامات الاقتباس */}
<h1 title="ملف المستخدم">الملف الشخصي</h1>
{/* سمات التعبيرات تستخدم الأقواس المعقوفة */}
<img src={imageUrl} alt={altText} />
{/* السمات المنطقية */}
<button disabled={!isActive}>إرسال</button>
{/* الأنماط المضمنة ككائنات */}
<p style={{ color: 'blue', fontSize: '18px' }}>
مرحباً بعودتك!
</p>
</div>
);
}
صيغة سمة Style: لاحظ الأقواس المعقوفة المزدوجة في سمة style: style={{ color: 'blue' }}. الأقواس الخارجية تشير إلى تعبير JavaScript، والأقواس الداخلية تنشئ كائن JavaScript. خصائص CSS تستخدم camelCase: fontSize، backgroundColor، إلخ.
العرض الشرطي
تتيح لك JSX عرض المحتوى بشكل مشروط باستخدام عدة تقنيات:
1. العامل الثلاثي (condition ? true : false)
function LoginButton({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>تسجيل خروج</button>
) : (
<button>تسجيل دخول</button>
)}
</div>
);
}
2. عامل AND المنطقي (&&)
استخدم && عندما تريد عرض شيء فقط إذا كان الشرط صحيحاً:
function Notification({ hasNewMessages, messageCount }) {
return (
<div>
<h1>لوحة التحكم</h1>
{hasNewMessages && (
<div className="alert">
لديك {messageCount} رسائل جديدة!
</div>
)}
</div>
);
}
كيف يعمل && في JSX: يقيّم JavaScript condition && expression. إذا كان الشرط صحيحاً، يُرجع التعبير. إذا كان خطأ، يُرجع false (الذي لا يعرضه React). هذه طريقة موجزة لعرض العناصر بشكل مشروط.
3. متغيرات العنصر
للشروط المعقدة، قم بتخزين JSX في متغيرات:
function Greeting({ user }) {
let content;
if (user.isAdmin) {
content = <h1>مرحباً بعودتك، مشرف {user.name}!</h1>;
} else if (user.isVIP) {
content = <h1>مرحباً، VIP {user.name}!</h1>;
} else {
content = <h1>مرحباً، {user.name}!</h1>;
}
return (
<div>
{content}
<p>آخر تسجيل دخول: {user.lastLogin}</p>
</div>
);
}
عرض القوائم
لعرض القوائم في React، استخدم طريقة .map() في JavaScript لتحويل المصفوفات إلى عناصر JSX:
function ShoppingList() {
const items = ['تفاح', 'موز', 'برتقال', 'حليب', 'خبز'];
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
للكائنات ذات المعرّفات الفريدة، استخدم المعرّف كمفتاح:
function UserList() {
const users = [
{ id: 1, name: 'علي', email: 'ali@example.com' },
{ id: 2, name: 'فاطمة', email: 'fatima@example.com' },
{ id: 3, name: 'محمد', email: 'mohamed@example.com' }
];
return (
<div>
{users.map(user => (
<div key={user.id} className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
))}
</div>
);
}
خاصية "key" مطلوبة: عند عرض القوائم، يتطلب React خاصية key فريدة لكل عنصر. يساعد هذا React في تحديد العناصر التي تغيرت أو أضيفت أو أزيلت. استخدم دائماً معرفات مستقرة وفريدة عندما تكون متاحة. تجنب استخدام فهارس المصفوفة كمفاتيح للقوائم الديناميكية (لا بأس للقوائم الثابتة التي لا تتغير أبداً).
React Fragments
تتيح لك React Fragments تجميع عناصر متعددة دون إضافة عقد إضافية إلى DOM:
// استخدام React.Fragment (الصيغة الطويلة)
function Table() {
return (
<table>
<tbody>
<React.Fragment>
<tr><td>الصف 1</td></tr>
<tr><td>الصف 2</td></tr>
</React.Fragment>
</tbody>
</table>
);
}
// استخدام اختصار Fragment (موصى به)
function Table() {
return (
<table>
<tbody>
<>
<tr><td>الصف 1</td></tr>
<tr><td>الصف 2</td></tr>
</>
</tbody>
</table>
);
}
متى تستخدم Fragments: استخدم fragments عندما تحتاج إلى إرجاع عناصر متجاورة متعددة دون تغليفها في <div>. هذا مفيد بشكل خاص للحفاظ على بنية HTML الصحيحة (مثل في الجداول) وتجنب التداخل غير الضروري في DOM.
يمكن أن تقبل Fragments أيضاً سمة key عند عرض القوائم (ولكن فقط مع الصيغة الطويلة):
function Glossary({ items }) {
return (
<dl>
{items.map(item => (
<React.Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.definition}</dd>
</React.Fragment>
))}
</dl>
);
}
التعليقات في JSX
إضافة التعليقات في JSX تتطلب صيغة خاصة:
function Example() {
return (
<div>
{/* هذا تعليق سطر واحد في JSX */}
{/*
هذا تعليق
متعدد الأسطر
في JSX
*/}
<h1>مرحباً بالعالم</h1>
{/* التعليقات داخل السمات تعمل أيضاً */}
<input
type="text"
{/* disabled */}
placeholder="أدخل النص"
/>
</div>
);
}
// التعليقات العادية في JavaScript تعمل خارج JSX
// هذا تعليق عادي
JSX مقابل HTML: ملخص الاختلافات الرئيسية
اختلافات HTML مقابل JSX:
1. سمة Class:
HTML: class="my-class"
JSX: className="my-class"
2. سمة For:
HTML: <label for="input">
JSX: <label htmlFor="input">
3. الوسوم ذاتية الإغلاق:
HTML: <img src="photo.jpg">
JSX: <img src="photo.jpg" />
4. سمة Style:
HTML: style="color: red; font-size: 18px"
JSX: style={{ color: 'red', fontSize: '18px' }}
5. معالجات الأحداث:
HTML: onclick="handleClick()"
JSX: onClick={handleClick}
6. السمات المنطقية:
HTML: <input disabled>
JSX: <input disabled={true} /> أو <input disabled />
7. عناصر جذر متعددة:
HTML: يمكن أن تحتوي على متعددة
JSX: يجب أن تحتوي على أصل واحد أو Fragment
التمرين 1: ممارسة JSX الأساسية
أنشئ مكوناً يسمى PersonCard يعرض معلومات الشخص. استخدم JSX لعرض:
- عنوان مع الاسم الكامل للشخص
- فقرة مع عمره (احسب السنوات حتى 100)
- صورة مع صورته الرمزية (استخدم عنوان URL احتياطي)
- فقرة تظهر "نشط" إذا كان نشطاً، وإلا "غير نشط"
- طبق فئات CSS وأنماط مضمنة
البيانات المستخدمة:
const person = {
firstName: 'محمد',
lastName: 'أحمد',
age: 28,
avatar: 'https://via.placeholder.com/150',
isActive: true
};
التمرين 2: العرض الشرطي
أنشئ مكون WeatherCard يعرض معلومات الطقس بالعرض الشرطي:
- أظهر أيقونة شمس ☀️ إذا كانت درجة الحرارة > 25°C
- أظهر أيقونة سحابة ☁️ إذا كانت درجة الحرارة بين 15-25°C
- أظهر أيقونة ثلج ❄️ إذا كانت درجة الحرارة < 15°C
- اعرض رسالة تحذير إذا كانت درجة الحرارة > 35°C أو < 0°C
- أظهر "أحضر مظلة" إذا كان isRaining صحيحاً
البيانات المستخدمة:
const weather = {
temperature: 28,
isRaining: false,
location: 'الرياض'
};
التمرين 3: عرض القوائم
أنشئ مكون Bookshelf يعرض قائمة من الكتب:
- قم بالتنقل عبر مصفوفة الكتب لإنشاء بطاقة لكل كتاب
- يجب أن تظهر كل بطاقة: العنوان والمؤلف والسنة والتقييم
- أضف نجمة ⭐ لكل نقطة تقييم (مثل 5 نجوم للتقييم 5)
- طبق ألوان خلفية مختلفة بناءً على التقييم (أخضر > 4، أصفر 3-4، أحمر < 3)
- استخدم مفاتيح مناسبة لعناصر القائمة
البيانات المستخدمة:
const books = [
{ id: 1, title: '1984', author: 'جورج أورويل', year: 1949, rating: 5 },
{ id: 2, title: 'قتل طائر محاكي', author: 'هاربر لي', year: 1960, rating: 5 },
{ id: 3, title: 'غاتسبي العظيم', author: 'ف. سكوت فيتزجيرالد', year: 1925, rating: 4 },
{ id: 4, title: 'موبي ديك', author: 'هيرمان ملفيل', year: 1851, rating: 3 }
];
الملخص
في هذا الدرس، أتقنت أساسيات JSX:
- JSX هو امتداد صيغة يبدو مثل HTML لكنه في الواقع JavaScript
- يجب إغلاق جميع وسوم JSX (ذاتية الإغلاق للوسوم الفردية)
- استخدم
className بدلاً من class، htmlFor بدلاً من for
- ضمّن تعبيرات JavaScript في JSX باستخدام الأقواس المعقوفة
{}
- سمات JSX تستخدم camelCase (onClick، onChange، إلخ)
- العرض الشرطي يستخدم عوامل ثلاثية، عامل &&، أو متغيرات العنصر
- عرض القوائم باستخدام
.map() مع خصائص key فريدة
- React Fragments (
<></>) تجمع العناصر دون عقد DOM إضافية
- التعليقات في JSX تستخدم صيغة
{/* تعليق */}
في الدرس التالي، سنستكشف مكونات React بعمق، ونتعلم كيفية إنشاء قطع قابلة لإعادة الاستخدام والتركيب من واجهة المستخدم مع المكونات الوظيفية!