תחביר JSX

מהו JSX?

JSX (JavaScript XML) הוא תחביר שמאפשר לכתוב קוד שנראה כמו HTML ישירות בתוך JavaScript. חשוב להבין שזה אינו HTML אמיתי - לפני שהקוד מגיע לדפדפן הוא מתקמפל ל-JavaScript רגיל. JSX הוא בסך הכול "סוכר תחבירי" שהופך את בניית הממשק לקריאה ונוחה יותר.

// JSX
const element = <h1>שלום עולם!</h1>;

// מה שזה הופך להיות (React.createElement)
const element = React.createElement('h1', null, 'שלום עולם!');

כללי תחביר בסיסיים

1. אלמנט שורש יחיד

כל קומפוננטה חייבת להחזיר אלמנט עוטף אחד בלבד. אפשר לעטוף את התוכן ב-div, ואם לא רוצים להוסיף תגית מיותרת ל-DOM - להשתמש ב-Fragment:

// ❌ שגוי - שני אלמנטים שורש
function Bad() {
    return (
        <h1>כותרת</h1>
        <p>תוכן</p>
    );
}

// ✅ נכון - עטיפה ב-div
function Good() {
    return (
        <div>
            <h1>כותרת</h1>
            <p>תוכן</p>
        </div>
    );
}

// ✅ נכון - שימוש ב-Fragment
function Better() {
    return (
        <>
            <h1>כותרת</h1>
            <p>תוכן</p>
        </>
    );
}

2. סגירת תגיות

כל התגיות חייבות להיסגר:

// ✅ תגיות עם תוכן
<div>תוכן</div>
<p>פסקה</p>

// ✅ תגיות self-closing
<img src="image.jpg" />
<br />
<input type="text" />
<hr />

3. camelCase לתכונות

מכיוון ש-JSX הוא בעצם JavaScript, חלק משמות התכונות משתנים לעומת HTML רגיל ונכתבים ב-camelCase. שימו לב במיוחד למילים השמורות class ו-for, שהופכות ל-className ו-htmlFor:

// HTML רגיל          // JSX
// class="..."    →   className="..."
// for="..."      →   htmlFor="..."
// onclick="..."  →   onClick={...}
// tabindex="..." →   tabIndex={...}

<label htmlFor="name" className="label">
    שם:
    <input id="name" tabIndex={1} />
</label>

ביטויים בסוגריים מסולסלים

הסוגריים המסולסלים {} הם הגשר בין ה-JSX ל-JavaScript: כל ביטוי שנכתב בתוכם מחושב, והתוצאה מוצגת במסך. אפשר להכניס אליהם משתנים, חישובים, קריאות לפונקציות ותנאים:

משתנים

const name = "דני";
const age = 25;

return (
    <div>
        <h1>שלום {name}!</h1>
        <p>גיל: {age}</p>
    </div>
);

ביטויים חשבוניים

return (
    <div>
        <p>2 + 2 = {2 + 2}</p>
        <p>מספר אקראי: {Math.random()}</p>
        <p>גיל בעוד 10 שנים: {age + 10}</p>
    </div>
);

קריאות לפונקציות

function formatDate(date) {
    return date.toLocaleDateString('he-IL');
}

return <p>תאריך: {formatDate(new Date())}</p>;

ביטויי תנאי (Ternary)

const isLoggedIn = true;

return (
    <div>
        {isLoggedIn ? <p>שלום משתמש!</p> : <p>אנא התחבר</p>}
    </div>
);

אובייקטים ומערכים

const user = { name: "דני", age: 25 };
const colors = ["אדום", "ירוק", "כחול"];

return (
    <div>
        <p>שם: {user.name}</p>
        <p>צבע ראשון: {colors[0]}</p>
    </div>
);

סגנונות (Styles)

Inline Styles

// סגנונות כאובייקט JavaScript
const style = {
    color: 'blue',
    fontSize: '20px',        // camelCase!
    backgroundColor: '#f0f0f0',
    padding: '10px'
};

return <p style={style}>טקסט מעוצב</p>;

// או inline
return (
    <p style={{ color: 'red', fontWeight: 'bold' }}>
        טקסט אדום ומודגש
    </p>
);

CSS Classes

// App.css
// .title { color: blue; font-size: 24px; }
// .highlight { background-color: yellow; }

import './App.css';

function App() {
    return (
        <h1 className="title highlight">כותרת</h1>
    );
}

Classes דינמיים

const isActive = true;
const isError = false;

return (
    <div className={`box ${isActive ? 'active' : ''} ${isError ? 'error' : ''}`}>
        תוכן
    </div>
);

Fragments

Fragment מאפשר לקבץ כמה אלמנטים יחד מבלי להוסיף תגית עוטפת מיותרת ל-DOM. הוא פותר בדיוק את מגבלת "אלמנט השורש היחיד", בלי לזהם את מבנה העמוד ב-div נוסף:

import { Fragment } from 'react';

// תחביר מלא
function List() {
    return (
        <Fragment>
            <li>פריט 1</li>
            <li>פריט 2</li>
            <li>פריט 3</li>
        </Fragment>
    );
}

// תחביר מקוצר (נפוץ יותר)
function List() {
    return (
        <>
            <li>פריט 1</li>
            <li>פריט 2</li>
            <li>פריט 3</li>
        </>
    );
}

// עם key (רק בתחביר המלא)
function Items({ items }) {
    return items.map(item => (
        <Fragment key={item.id}>
            <dt>{item.term}</dt>
            <dd>{item.description}</dd>
        </Fragment>
    ));
}

הערות ב-JSX

function App() {
    return (
        <div>
            {/* זו הערה ב-JSX */}
            <h1>כותרת</h1>

            {/* 
                הערה
                בכמה
                שורות 
            */}
            <p>תוכן</p>
        </div>
    );
}

דברים שאי אפשר לעשות ב-JSX

בתוך הסוגריים המסולסלים אפשר לכתוב ביטויים (expressions) בלבד - כלומר קוד שמחזיר ערך. משפטי בקרה כמו if או לולאת for אינם ביטויים, ולכן במקומם משתמשים ב-ternary, באופרטור && ובמתודה map:

// ❌ שגוי - if/else רגיל לא עובד בתוך JSX
function Bad() {
    return (
        <div>
            {if (condition) { <p>כן</p> }}  // שגיאה!
        </div>
    );
}

// ✅ השתמשו ב-ternary או &&
function Good() {
    return (
        <div>
            {condition ? <p>כן</p> : <p>לא</p>}
            {condition && <p>מוצג רק אם true</p>}
        </div>
    );
}

// ❌ for loop ישירות - לא עובד
function Bad() {
    return (
        <ul>
            {for (let i = 0; i < 3; i++) { <li>{i}</li> }}  // שגיאה!
        </ul>
    );
}

// ✅ השתמשו ב-map
function Good() {
    return (
        <ul>
            {[0, 1, 2].map(i => <li key={i}>{i}</li>)}
        </ul>
    );
}

סיכום תחביר JSX

כלל דוגמה
אלמנט שורש יחיד <> ... </>
סגירת תגיות <img />
className <div className="box">
htmlFor <label htmlFor="id">
ביטויים בסוגריים {variable}
Inline styles style={{ color: 'red' }}
הערות {/* הערה */}

הקודם: ← התקנה והגדרות
הבא: קומפוננטות →

בדקו את עצמכם

נסו לענות לבד לפני שאתם פותחים את התשובה.

  1. איך כותבים class של CSS ב-JSX?

    1. style
    2. cssClass
    3. class
    4. className
    הצגת התשובה

    תשובה ד. class היא מילה שמורה ב-JavaScript, ולכן JSX משתמש ב-className.

  2. מה מחזירה קומפוננטה שמנסה להחזיר שני אלמנטים צמודים בלי עטיפה?

    1. רק האחרון מוצג
    2. שגיאה: חייב אלמנט הורה אחד, או Fragment
    3. רק האלמנט הראשון מוצג
    4. עובד רגיל
    הצגת התשובה

    תשובה ב. עוטפים ב-<>...</> (Fragment), שלא מוסיף אלמנט ל-DOM.

  3. איך מכניסים ערך JavaScript לתוך JSX?

    1. {{value}}
    2. @value
    3. {value}
    4. ${value}
    הצגת התשובה

    תשובה ג. סוגריים מסולסלים בודדים מפעילים ביטוי JavaScript.