Урок 07

Обработка событий

События в React похожи на DOM-события, но есть отличия: camelCase, передача функции, а не строки.

onClick

function Button() {
    function handleClick() {
        alert('Клик');
    }

    return <button onClick={handleClick}>Нажми</button>;
}

Важно: передаётся функция, а не её вызов.

<button onClick={handleClick}>OK</button>      // правильно
<button onClick={handleClick()}>Ошибка</button> // вызовется сразу при рендере

Инлайн-функция

<button onClick={() => alert('Клик')}>Нажми</button>

Полезно, когда нужно передать аргумент:

<button onClick={() => deleteItem(item.id)}>Удалить</button>

Аргумент события

React передаёт объект события в функцию:

function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
    console.log(event.target.value);
}

<input onChange={handleChange} />

Основные события

  • onClick — клик
  • onChange — изменение значения (для input)
  • onSubmit — отправка формы
  • onFocus / onBlur — фокус
  • onMouseEnter / onMouseLeave — мышь
  • onKeyDown / onKeyUp — клавиши
  • onScroll — скролл
  • onLoad — загрузка

preventDefault

Для отмены поведения по умолчанию:

function Form() {
    function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
        event.preventDefault();
        // обработка
    }

    return (
        <form onSubmit={handleSubmit}>
            <button type="submit">Отправить</button>
        </form>
    );
}

Без preventDefault браузер перезагрузит страницу.

stopPropagation

Останавливает всплытие:

function Card() {
    return (
        <div onClick={() => console.log('card')}>
            <button onClick={(e) => {
                e.stopPropagation();
                console.log('button');
            }}>
                Кнопка
            </button>
        </div>
    );
}

Без stopPropagation клик по кнопке вызовет оба обработчика.

Передача аргументов

Через стрелочную функцию:

{items.map((item) => (
    <button key={item.id} onClick={() => handleDelete(item.id)}>
        Удалить
    </button>
))}

Через bind (реже):

<button onClick={handleDelete.bind(null, item.id)}>Удалить</button>

Обработчики в родителе

Часто обработчик живёт в родителе, а вызывается в ребёнке через пропс:

function Parent() {
    function handleDelete(id: number) {
        console.log('Удалить', id);
    }

    return <Child onDelete={handleDelete} />;
}

function Child({ onDelete }: { onDelete: (id: number) => void }) {
    return <button onClick={() => onDelete(5)}>Удалить</button>;
}

События клавиатуры

function Input() {
    function handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
        if (event.key === 'Enter') {
            console.log('Enter нажат');
        }
    }

    return <input onKeyDown={handleKeyDown} />;
}

Итоги

  • События в camelCase: onClick, onChange, onSubmit
  • Передаётся функция, не вызов
  • Аргумент — объект события
  • preventDefault отменяет действие по умолчанию
  • stopPropagation останавливает всплытие
  • Аргументы передаются через стрелочную функцию