Урок 01

События в React

Событие — это действие пользователя или браузера: клик, ввод текста, отправка формы, нажатие клавиши. React предоставляет единый синтетический слой над DOM-событиями.

Синтетические события

React оборачивает нативные события в SyntheticEvent. Это объект с тем же интерфейсом, что и нативное событие, но работающий одинаково во всех браузерах.

function Button() {
    function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
        console.log(e.type); // click
        console.log(e.target); // кнопка
    }

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

Именование

В React события пишутся в camelCase: onClick, onChange, onSubmit. В HTML — onclick, onchange, onsubmit.

Передача функции

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

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

Если нужен вызов с аргументом — оборачивай в стрелочную функцию:

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

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

  • onClick — клик мышью
  • onDoubleClick — двойной клик
  • onChange — изменение значения input, select, textarea
  • onInput — ввод в поле
  • onSubmit — отправка формы
  • onFocus / onBlur — фокус и потеря фокуса
  • onMouseEnter / onMouseLeave — вход/выход мыши
  • onMouseDown / onMouseUp — нажатие/отпускание кнопки мыши
  • onKeyDown / onKeyUp / onKeyPress — клавиши
  • onScroll — прокрутка
  • onLoad — загрузка
  • onError — ошибка
  • onCopy / onPaste / onCut — буфер обмена
  • onDragStart / onDrop — drag-and-drop

Объект события

function Input() {
    function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
        console.log(e.target.value);
        console.log(e.target.name);
        console.log(e.target.type);
    }

    return <input onChange={handleChange} />;
}

e.target — элемент, на котором произошло событие. e.currentTarget — элемент, к которому привязан обработчик.

preventDefault

Отменяет поведение браузера по умолчанию:

function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    // обработка без перезагрузки
}

Примеры:

  • Форма — не перезагружать страницу
  • Ссылка — не переходить по URL
  • Клавиша — не вводить символ

stopPropagation

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

function Card() {
    return (
        <div onClick={() => console.log('card')}>
            <button onClick={(e) => {
                e.stopPropagation();
                console.log('button');
            }}>
                OK
            </button>
        </div>
    );
}

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

Типизация событий

TypeScript позволяет точно указать тип события:

function handleClick(e: React.MouseEvent<HTMLButtonElement>) {}
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {}
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {}
function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {}
function handleFocus(e: React.FocusEvent<HTMLInputElement>) {}

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

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

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>;
}

Итоги

  • События — camelCase
  • Передаётся функция, не вызов
  • SyntheticEvent работает одинаково в браузерах
  • preventDefault отменяет поведение по умолчанию
  • stopPropagation останавливает всплытие
  • Тип события — React.MouseEvent<HTMLButtonElement> и т. д.