Як типізувати обробники подій?
Базовий принцип
- Усі події - це нащадки
React.SyntheticEvent. - У обробників є елемент, до якого вони прив'язані:
HTMLInputElement,HTMLButtonElement,HTMLFormElement,HTMLDivElementтощо. - Зручні алiаси-коллбеки:
React.MouseEventHandler<T>,React.ChangeEventHandler<T>та ін.
javascript
// Універсальний вигляд
const handle = (e: React.SyntheticEvent<HTMLDivElement>) => { /* ... */ };
// З алiасом (рекомендовано, коротше)
const onClick: React.MouseEventHandler<HTMLButtonElement> = (e) => { /* ... */ };Часті випадки
Click (миша)
javascript
const onClick: React.MouseEventHandler<HTMLButtonElement> = (e) => {
e.preventDefault();
};Change (input, select, textarea)
javascript
const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
const value = e.currentTarget.value; // коректно типізовано
};Submit (форма)
javascript
const onSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
};Keyboard
javascript
const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (e) => {
if (e.key === "Enter") { /* ... */ }
};Focus / Blur
javascript
const onFocus: React.FocusEventHandler<HTMLInputElement> = (e) => { /* ... */ };
const onBlur: React.FocusEventHandler<HTMLTextAreaElement> = (e) => { /* ... */ };Pointer / Mouse / Wheel
javascript
const onPointerDown: React.PointerEventHandler<HTMLDivElement> = (e) => {};
const onMouseEnter: React.MouseEventHandler<HTMLDivElement> = (e) => {};
const onWheel: React.WheelEventHandler<HTMLDivElement> = (e) => {};Drag & Drop
javascript
const onDragStart: React.DragEventHandler<HTMLDivElement> = (e) => {};
const onDrop: React.DragEventHandler<HTMLDivElement> = (e) => {
e.preventDefault();
};Clipboard
javascript
const onPaste: React.ClipboardEventHandler<HTMLInputElement> = (e) => {
const text = e.clipboardData.getData("text");
};Touch (мобільні)
javascript
const onTouchStart: React.TouchEventHandler<HTMLDivElement> = (e) => {};Animation / Transition
javascript
const onAnimationEnd: React.AnimationEventHandler<HTMLDivElement> = (e) => {};
const onTransitionEnd: React.TransitionEventHandler<HTMLDivElement> = (e) => {};Цінні прийоми
1) target vs currentTarget
- Використовуй
e.currentTarget- він завжди того типу, до якого прив'язаний обробник. e.targetможе бути вкладеним вузлом і типізується ширше (EventTarget).
javascript
const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
// правильно
e.currentTarget.value;
// e.target.value - не скомпілюється без приведення типу
};2) Вбудовування прямо в пропси компонента
javascript
<button onClick={(e: React.MouseEvent<HTMLButtonElement>) => { /* ... */ }} />3) Тип пропса-обробника у власних компонентах
javascript
type Props = {
onClick?: React.MouseEventHandler<HTMLButtonElement>;
};
const MyButton = ({ onClick }: Props) => <button onClick={onClick}>OK</button>;Або "позичити" сигнатуру з нативного елемента:
javascript
type ButtonProps = {
onClick?: React.ComponentProps<"button">["onClick"];
};4) Обробник, що читає всю форму цілком
javascript
const onSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
const form = e.currentTarget;
const data = new FormData(form);
const email = data.get("email");
};5) Універсальний колбек з generic
javascript
function handleChange<T extends HTMLInputElement | HTMLTextAreaElement>(
e: React.ChangeEvent<T>
) {
console.log(e.currentTarget.value);
}Швидкий довідник типів
React.MouseEvent<T>/React.MouseEventHandler<T>React.ChangeEvent<T>/React.ChangeEventHandler<T>React.FormEvent<T>/React.FormEventHandler<T>React.KeyboardEvent<T>/React.KeyboardEventHandler<T>React.FocusEvent<T>/React.FocusEventHandler<T>React.PointerEvent<T>/React.PointerEventHandler<T>React.DragEvent<T>/React.DragEventHandler<T>React.ClipboardEvent<T>/React.ClipboardEventHandler<T>React.WheelEvent<T>/React.WheelEventHandler<T>React.TouchEvent<T>/React.TouchEventHandler<T>React.AnimationEvent<T>/React.AnimationEventHandler<T>React.TransitionEvent<T>/React.TransitionEventHandler<T>
Де T - конкретний DOM-елемент:
HTMLInputElement, HTMLButtonElement, HTMLDivElement, HTMLFormElement, HTMLSelectElement, HTMLTextAreaElement, HTMLAnchorElement тощо.
Часті помилки
anyв обробниках - втрачаєш підказки і перевірки.- Використання
e.targetзамістьe.currentTarget. - Забули вказати тип елемента (наприклад,
HTMLInputElement) - доведеться вручну приводити типtarget.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.