לדלג לתוכן

6.1 הקדמה לריאקט ו JSX פתרון

פתרון - הקדמה לריאקט ו-JSX

פתרון תרגיל 1

א-ב. הקמה והרצה:

npm create vite@latest my-first-react -- --template react-ts
cd my-first-react
npm install
npm run dev

ג. קובץ src/App.tsx:

function App() {
    return (
        <div>
            <h1>Amit Pinchasi</h1>
            <p>I am a software developer who loves teaching.</p>
        </div>
    );
}

export default App;

ד. לאחר שמירת הקובץ, השינוי מופיע אוטומטית בדפדפן בלי ריענון ידני - זה HMR (Hot Module Replacement) של Vite.

פתרון תרגיל 2

function Profile() {
    const firstName = "Alice";
    const lastName = "Smith";
    const age = 30;
    const profession = "Software Developer";
    const hobbies = ["reading", "coding", "hiking", "cooking"];

    return (
        <div>
            <h1>{firstName} {lastName}</h1>
            <p>Age: {age} (in 10 years: {age + 10})</p>
            <p>Profession: {profession}</p>
            <p>Number of hobbies: {hobbies.length}</p>
            <p>Hobbies: {hobbies.join(", ")}</p>
            <p>Current date and time: {new Date().toLocaleString()}</p>
        </div>
    );
}

פתרון תרגיל 3

function StyledCard() {
    const isVIP = true;
    const fontSize = 18;
    const name = "Alice";

    const cardStyle = {
        backgroundColor: isVIP ? "#ffd700" : "#f0f0f0",
        fontSize: `${fontSize}px`,
        padding: "20px",
        borderRadius: "12px",
        border: isVIP ? "2px solid #b8860b" : "1px solid #ccc",
    };

    return (
        <div className="card" style={cardStyle}>
            <h2 className="card-title">{name}</h2>
            <p className="card-status">{isVIP ? "VIP Member" : "Regular Member"}</p>
        </div>
    );
}

function App() {
    return (
        <div>
            <StyledCard />
            {/* to show the non-VIP version, change isVIP inside the component */}
        </div>
    );
}

הערה: כרגע אין לנו props אז שני הכרטיסים יראו אותו דבר. בשיעור הבא נלמד להעביר נתונים לקומפוננטה דרך props.

פתרון תרגיל 4

function UserInfo() {
    const name = "Alice Smith";
    const email = "alice@example.com";
    const age = 30;

    return (
        <>
            <dt>Name</dt>
            <dd>{name}</dd>
            <dt>Email</dt>
            <dd>{email}</dd>
            <dt>Age</dt>
            <dd>{age}</dd>
        </>
    );
}

function App() {
    return (
        <dl>
            <UserInfo />
        </dl>
    );
}

אם היינו עוטפים ב-<div>, ה-HTML שנוצר היה:

<dl>
    <div>  <!-- this is invalid! dt/dd must be direct children of dl -->
        <dt>Name</dt>
        <dd>Alice Smith</dd>
        ...
    </div>
</dl>

Fragment פותר את הבעיה כי הוא לא מוסיף אלמנט ל-DOM.

פתרון תרגיל 5

function ProductCard() {
    const name = "Wireless Headphones";
    const price = 299.99;
    const description = "High-quality noise-cancelling wireless headphones.";
    const inStock = true;
    const discountPercent = 15;

    const discountedPrice = price * (1 - discountPercent / 100);

    return (
        <div style={{ border: "1px solid #ddd", padding: "16px", borderRadius: "8px" }}>
            <h2>{name}</h2>
            <p>{description}</p>
            <p>
                Price: ${price.toFixed(2)}
            </p>
            <p>
                Discount: {discountPercent}% off - Final price: ${discountedPrice.toFixed(2)}
            </p>
            <p style={{ color: inStock ? "green" : "red", fontWeight: "bold" }}>
                {inStock ? "In Stock" : "Out of Stock"}
            </p>
        </div>
    );
}

פתרון תרגיל 6

function Clock() {
    const now = new Date();
    const hour = now.getHours();

    const dateString = now.toLocaleDateString("he-IL");
    const dayOfWeek = now.toLocaleDateString("he-IL", { weekday: "long" });

    let timeOfDay: string;
    let greeting: string;

    if (hour >= 5 && hour < 12) {
        timeOfDay = "morning";
        greeting = "Good morning!";
    } else if (hour >= 12 && hour < 17) {
        timeOfDay = "afternoon";
        greeting = "Good afternoon!";
    } else if (hour >= 17 && hour < 21) {
        timeOfDay = "evening";
        greeting = "Good evening!";
    } else {
        timeOfDay = "night";
        greeting = "Good night!";
    }

    return (
        <>
            <h1>{greeting}</h1>
            <p>Date: {dateString}</p>
            <p>Day: {dayOfWeek}</p>
            <p>Time of day: {timeOfDay}</p>
            <p>Current time: {now.toLocaleTimeString()}</p>
        </>
    );
}

שימו לב שהלוגיקה של if/else נמצאת מחוץ ל-JSX, בחלק ה-JavaScript של הפונקציה. בתוך JSX אפשר להשתמש רק בביטויים.

תשובות לשאלות

  1. ספרייה נותנת כלים ספציפיים ואנחנו קוראים לה (אנחנו שולטים בזרימה). framework נותן מבנה שלם ומכתיב את הארכיטקטורה (ה-framework שולט בזרימה וקורא לקוד שלנו). ריאקט היא ספרייה - היא מטפלת רק ב-UI ומשאירה לנו את הבחירה בנושאים כמו ניתוב וניהול סטייט.

  2. SPA (Single Page Application) היא אפליקציה שטוענת דף HTML אחד ומעדכנת את התוכן דינמית עם JavaScript. היתרונות: חוויית משתמש חלקה בלי טעינה מחדש, ניווט מהיר בין דפים, וביצועים טובים כי רק הנתונים נטענים מהשרת (לא HTML שלם).

  3. ריאקט משתמשת באות הראשונה כדי להבדיל בין קומפוננטות לאלמנטי HTML. <div> - אלמנט HTML. <MyComponent> - קומפוננטה. אם נקרא לקומפוננטה <myComponent>, ריאקט תתייחס אליה כאלמנט HTML לא מוכר.

  4. class היא מילה שמורה ב-JavaScript (משמשת להגדרת מחלקות), אז ב-JSX (שהוא JavaScript) משתמשים ב-className במקום. באופן דומה, for (של label) הופך ל-htmlFor.

  5. צריך Fragments כשרוצים להחזיר כמה אלמנטים בלי להוסיף אלמנט עוטף ל-DOM. נעדיף Fragment על div כשהעטיפה תשבור את מבנה ה-HTML (כמו בדוגמת dl/dt/dd), או כשלא רוצים DOM מיותר שיכול לשבור CSS (למשל Flexbox או Grid).

  6. בתוך {} ב-JSX אפשר לשים כל ביטוי (expression) שמחזיר ערך: משתנים, חישובים, קריאות לפונקציות, ternary, שרשור מחרוזות. אי אפשר לשים statements כמו if, for, while, switch. הפתרון: לחשב את הערך מחוץ ל-JSX ולהשתמש במשתנה, או להשתמש ב-ternary/map בתוך ה-JSX.