אירועים (Events)

מבוא

אירועים הם הדרך שבה הממשק מגיב לפעולות המשתמש - לחיצה, הקלדה, מעבר עכבר ועוד. React משתמשת במערכת אירועים דומה מאוד לזו של HTML, אך עם שני הבדלים מרכזיים:

  • שמות האירועים נכתבים ב-camelCase (למשל onClick ולא onclick)
  • מעבירים פונקציה כערך, ולא מחרוזת של קוד
// HTML רגיל
<button onclick="handleClick()">לחץ</button>

// React
<button onClick={handleClick}>לחץ</button>

אירועים נפוצים

onClick - לחיצה

function Button() {
    const handleClick = () => {
        alert('לחצת על הכפתור!');
    };

    return <button onClick={handleClick}>לחץ עליי</button>;
}

// או inline
<button onClick={() => alert('לחצת!')}>לחץ</button>

onChange - שינוי ערך

function Input() {
    const [text, setText] = useState("");

    const handleChange = (event) => {
        setText(event.target.value);
    };

    return (
        <input 
            type="text" 
            value={text} 
            onChange={handleChange}
            placeholder="הקלד משהו..."
        />
    );
}

onSubmit - שליחת טופס

function Form() {
    const [name, setName] = useState("");

    const handleSubmit = (event) => {
        event.preventDefault(); // מונע רענון הדף
        console.log('שם:', name);
    };

    return (
        <form onSubmit={handleSubmit}>
            <input 
                value={name} 
                onChange={(e) => setName(e.target.value)} 
            />
            <button type="submit">שלח</button>
        </form>
    );
}

רשימת אירועים

אירועי עכבר

<div
    onClick={() => console.log('לחיצה')}
    onDoubleClick={() => console.log('לחיצה כפולה')}
    onMouseEnter={() => console.log('עכבר נכנס')}
    onMouseLeave={() => console.log('עכבר יצא')}
    onMouseMove={(e) => console.log(e.clientX, e.clientY)}
>
    עבור עם העכבר
</div>

אירועי מקלדת

<input
    onKeyDown={(e) => console.log('מקש למטה:', e.key)}
    onKeyUp={(e) => console.log('מקש למעלה:', e.key)}
    onKeyPress={(e) => {
        if (e.key === 'Enter') {
            console.log('Enter נלחץ!');
        }
    }}
/>

אירועי פוקוס

<input
    onFocus={() => console.log('קיבל פוקוס')}
    onBlur={() => console.log('איבד פוקוס')}
/>

אירועי טופס

<form onSubmit={handleSubmit} onReset={handleReset}>
    <input onChange={handleChange} />
    <select onChange={handleSelect} />
    <textarea onChange={handleTextChange} />
</form>

Event Object

כל פונקציית handler מקבלת אוטומטית אובייקט event שמתאר את האירוע שהתרחש. דרכו ניתן לגשת לאלמנט שהפעיל את האירוע, לערך שהוזן, למקש שנלחץ ולמידע נוסף:

function EventExample() {
    const handleClick = (event) => {
        console.log('סוג האירוע:', event.type);
        console.log('אלמנט מקור:', event.target);
        console.log('מיקום X:', event.clientX);
        console.log('מיקום Y:', event.clientY);
        console.log('מקש Ctrl לחוץ?', event.ctrlKey);
    };

    const handleInput = (event) => {
        console.log('ערך חדש:', event.target.value);
        console.log('שם השדה:', event.target.name);
    };

    return (
        <div>
            <button onClick={handleClick}>לחץ</button>
            <input name="username" onChange={handleInput} />
        </div>
    );
}

preventDefault ו-stopPropagation

שתי מתודות של אובייקט האירוע שכדאי להכיר: preventDefault מבטלת את התנהגות ברירת המחדל של הדפדפן (כמו רענון הדף בשליחת טופס או ניווט בלחיצה על קישור), ו-stopPropagation עוצרת את בעבוע האירוע כלפי מעלה, כך שאירוע בקומפוננטה פנימית לא יפעיל בטעות handler של קומפוננטה עוטפת:

// preventDefault - מונע התנהגות ברירת מחדל
function Link() {
    const handleClick = (e) => {
        e.preventDefault(); // מונע ניווט
        console.log('הלינק נלחץ');
    };

    return <a href="https://google.com" onClick={handleClick}>לינק</a>;
}

// stopPropagation - עוצר את בועת האירוע
function Nested() {
    return (
        <div onClick={() => console.log('חיצוני')}>
            <button onClick={(e) => {
                e.stopPropagation();
                console.log('פנימי');
            }}>
                לחץ
            </button>
        </div>
    );
    // בלי stopPropagation: "פנימי" ואז "חיצוני"
    // עם stopPropagation: רק "פנימי"
}

העברת פרמטרים נוספים

שיטה 1: Arrow Function

function List() {
    const items = ['תפוח', 'בננה', 'תפוז'];

    const handleClick = (item) => {
        console.log('נבחר:', item);
    };

    return (
        <ul>
            {items.map(item => (
                <li key={item}>
                    <button onClick={() => handleClick(item)}>
                        {item}
                    </button>
                </li>
            ))}
        </ul>
    );
}

שיטה 2: data attributes

function List() {
    const handleClick = (event) => {
        const item = event.target.dataset.item;
        console.log('נבחר:', item);
    };

    return (
        <ul>
            {['תפוח', 'בננה', 'תפוז'].map(item => (
                <li key={item}>
                    <button data-item={item} onClick={handleClick}>
                        {item}
                    </button>
                </li>
            ))}
        </ul>
    );
}

אירוע + State

function Counter() {
    const [count, setCount] = useState(0);

    return (
        <div>
            <p>ספירה: {count}</p>
            <button onClick={() => setCount(c => c + 1)}>הוסף</button>
            <button onClick={() => setCount(c => c - 1)}>הפחת</button>
            <button onClick={() => setCount(0)}>אפס</button>
        </div>
    );
}

function Toggle() {
    const [isOn, setIsOn] = useState(false);

    return (
        <button onClick={() => setIsOn(prev => !prev)}>
            {isOn ? '🔵 פועל' : '⚪ כבוי'}
        </button>
    );
}

דוגמה מלאה: טופס

function ContactForm() {
    const [formData, setFormData] = useState({
        name: '',
        email: '',
        message: ''
    });
    const [submitted, setSubmitted] = useState(false);

    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData(prev => ({
            ...prev,
            [name]: value
        }));
    };

    const handleSubmit = (e) => {
        e.preventDefault();
        console.log('נתוני הטופס:', formData);
        setSubmitted(true);
    };

    if (submitted) {
        return <p>תודה {formData.name}! ההודעה נשלחה.</p>;
    }

    return (
        <form onSubmit={handleSubmit}>
            <input
                name="name"
                value={formData.name}
                onChange={handleChange}
                placeholder="שם"
            />
            <input
                name="email"
                type="email"
                value={formData.email}
                onChange={handleChange}
                placeholder="אימייל"
            />
            <textarea
                name="message"
                value={formData.message}
                onChange={handleChange}
                placeholder="הודעה"
            />
            <button type="submit">שלח</button>
        </form>
    );
}

סיכום אירועים

אירוע שימוש
onClick לחיצה על אלמנט
onChange שינוי ערך (input, select)
onSubmit שליחת טופס
onKeyDown לחיצת מקש
onMouseEnter עכבר נכנס
onMouseLeave עכבר יוצא
onFocus קבלת פוקוס
onBlur איבוד פוקוס

הקודם: ← State
הבא: Hooks →

בדקו את עצמכם

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

  1. מה ההבדל בין onClick={handleClick} ל-onClick={handleClick()}?

    1. אין הבדל
    2. הראשון מעביר פונקציה, השני מפעיל אותה מיד בזמן הרינדור
    3. הראשון לא עובד
    4. השני מהיר יותר
    הצגת התשובה

    תשובה ב. עם סוגריים הפונקציה רצה מיד. כשצריך ארגומנט: onClick={() => handleClick(id)}.

  2. איך נקראים אירועים ב-React?

    1. click
    2. onClick (camelCase)
    3. onclick (קטנות)
    4. on-click
    הצגת התשובה

    תשובה ב. React משתמשת ב-camelCase לכל האירועים.