Пошук уроків, статей та іншого контенту
Освоїте типізацію обробників кліків, введення тексту, submit та інших React-подій.
У React обробники подій отримують об’єкт події. TypeScript допомагає:
визначити, з якого елемента надійшла подія;
безпечно читати value, checked та інші властивості;
не плутати типи подій;
отримувати підказки від редактора коду;
знаходити помилки ще до запуску застосунку.
Наприклад, для текстового поля потрібна подія ChangeEvent, а для форми — FormEvent.
Для кліку використовується React.MouseEvent.
import type { MouseEvent } from "react";
function ClickExample() {
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
console.log("Натиснуто:", event.currentTarget.textContent);
};
return <button onClick={handleClick}>Натиснути</button>;
}HTMLButtonElement вказує, що подія відбулася на кнопці.
Для інших елементів потрібно вказати відповідний тип:
import type { MouseEvent } from "react";
function LinkExample() {
const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
console.log("Клік за посиланням:", event.currentTarget.href);
};
return (
<a href="/profile" onClick={handleClick}>
Профіль
</a>
);
}Обробник можна типізувати не лише через параметр, а й через тип функції:
import type { MouseEventHandler } from "react";
const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {
console.log(event.currentTarget.disabled);
};Обидва варіанти коректні:
import type { MouseEvent, MouseEventHandler } from "react";
const firstHandler = (event: MouseEvent<HTMLButtonElement>) => {
console.log(event.currentTarget.textContent);
};
const secondHandler: MouseEventHandler<HTMLButtonElement> = (event) => {
console.log(event.currentTarget.textContent);
};Для події onChange на текстовому полі використовується React.ChangeEvent.
import type { ChangeEvent } from "react";
function SearchInput() {
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
console.log(event.currentTarget.value);
};
return <input type="text" onChange={handleChange} />;
}Для textarea тип елемента буде іншим:
import type { ChangeEvent } from "react";
function CommentInput() {
const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
console.log(event.currentTarget.value);
};
return <textarea onChange={handleChange} />;
}У контрольованому полі значення зберігається у стані, а onChange оновлює цей стан.
import { useState, type ChangeEvent } from "react";
function NameInput() {
const [name, setName] = useState("");
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setName(event.currentTarget.value);
};
return (
<label>
Ім’я:
<input value={name} onChange={handleChange} />
<p>Введено: {name}</p>
</label>
);
}event.currentTarget.value має тип string, тому TypeScript знає, що це значення можна передати в setName.
Для checkbox значення потрібно читати з checked, а не з value.
import { useState, type ChangeEvent } from "react";
function AgreementCheckbox() {
const [accepted, setAccepted] = useState(false);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setAccepted(event.currentTarget.checked);
};
return (
<label>
<input
type="checkbox"
checked={accepted}
onChange={handleChange}
/>
Погоджуюся з умовами
</label>
);
}event.currentTarget.value — текстове значення елемента;
event.currentTarget.checked — boolean для checkbox або radio.
Для onSubmit використовується React.FormEvent<HTMLFormElement>.
import type { FormEvent } from "react";
function LoginForm() {
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
console.log("Форму надіслано");
};
return (
<form onSubmit={handleSubmit}>
<input type="email" />
<button type="submit">Увійти</button>
</form>
);
}Метод preventDefault() скасовує стандартне перезавантаження сторінки під час надсилання форми.
Найпростіше зберігати значення полів у стані:
import { useState, type FormEvent } from "react";
function LoginForm() {
const [email, setEmail] = useState("");
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
console.log({
email,
});
};
return (
<form onSubmit={handleSubmit}>
<label>
Електронна пошта:
<input
type="email"
value={email}
onChange={(event) => setEmail(event.currentTarget.value)}
/>
</label>
<button type="submit">Увійти</button>
</form>
);
}Для кнопки надсилання важливо вказувати type="submit". Обробник форми спрацює саме через onSubmit.
Для натискання клавіш використовується React.KeyboardEvent.
import type { KeyboardEvent } from "react";
function SearchBox() {
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter") {
console.log("Пошук запущено");
}
};
return <input onKeyDown={handleKeyDown} placeholder="Пошук" />;
}Поширені властивості клавіатурної події:
event.key — назва натиснутої клавіші, наприклад "Enter";
event.code — фізична клавіша, наприклад "Enter";
event.currentTarget — елемент, на якому зареєстровано обробник.
Для фокусу та втрати фокусу використовуються FocusEvent.
import type { FocusEvent } from "react";
function EmailField() {
const handleFocus = (event: FocusEvent<HTMLInputElement>) => {
console.log("Фокус отримано:", event.currentTarget.name);
};
const handleBlur = (event: FocusEvent<HTMLInputElement>) => {
console.log("Фокус втрачено:", event.currentTarget.value);
};
return (
<input
name="email"
onFocus={handleFocus}
onBlur={handleBlur}
/>
);
}target і currentTargetЦі властивості схожі, але мають різний сенс:
target — елемент, на якому фактично виникла подія;
currentTarget — елемент, на якому працює поточний обробник.
У більшості обробників форм зручно використовувати currentTarget, оскільки його тип відповідає типу, вказаному в події.
import type { MouseEvent } from "react";
function Button() {
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
const button = event.currentTarget;
console.log(button.textContent);
console.log(button.disabled);
};
return <button onClick={handleClick}>Зберегти</button>;
}Для target TypeScript не завжди може визначити конкретний тип елемента, адже подія могла виникнути на вкладеному елементі.
Якщо обробник написано безпосередньо в JSX, TypeScript часто сам виводить тип події:
function Form() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
}}
>
<input
onChange={(event) => {
console.log(event.currentTarget.value);
}}
/>
</form>
);
}У цьому прикладі:
для onSubmit TypeScript визначає FormEvent<HTMLFormElement>;
для onChange на input — ChangeEvent<HTMLInputElement>.
Явна типізація потрібна, коли обробник винесено в окрему функцію або коли потрібно краще пояснити його контракт.
Нижче наведено компонент, який поєднує типізацію введення, кліку, клавіатури та надсилання форми.
import { useState, type ChangeEvent, type FormEvent, type KeyboardEvent } from "react";
export default function TodoForm() {
const [task, setTask] = useState("");
const [submittedTask, setSubmittedTask] = useState("");
const handleTaskChange = (event: ChangeEvent<HTMLInputElement>) => {
setTask(event.currentTarget.value);
};
const handleTaskKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Escape") {
setTask("");
}
};
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const trimmedTask = task.trim();
if (trimmedTask === "") {
return;
}
setSubmittedTask(trimmedTask);
setTask("");
};
const handleClear = () => {
setSubmittedTask("");
};
return (
<section>
<h2>Нове завдання</h2>
<form onSubmit={handleSubmit}>
<label>
Назва завдання:
<input
value={task}
onChange={handleTaskChange}
onKeyDown={handleTaskKeyDown}
placeholder="Наприклад, прочитати документацію"
/>
</label>
<button type="submit">Додати</button>
</form>
{submittedTask && (
<div>
<p>Останнє завдання: {submittedTask}</p>
<button type="button" onClick={handleClear}>
Очистити
</button>
</div>
)}
</section>
);
}У цьому компоненті:
ChangeEvent<HTMLInputElement> описує зміни текстового поля;
KeyboardEvent<HTMLInputElement> описує натискання клавіш у полі;
FormEvent<HTMLFormElement> описує надсилання форми;
onClick={handleClear} обробляє клік кнопки;
event.preventDefault() не дає браузеру перезавантажити сторінку.
| JSX-подія | Тип події | |---|---| | onClick | MouseEvent<HTMLElement> | | onChange | ChangeEvent<HTMLInputElement> | | onSubmit | FormEvent<HTMLFormElement> | | onKeyDown | KeyboardEvent<HTMLInputElement> | | onFocus | FocusEvent<HTMLInputElement> | | onBlur | FocusEvent<HTMLInputElement> |
Конкретний тип HTML-елемента потрібно змінювати відповідно до компонента:
HTMLButtonElement — кнопка;
HTMLInputElement — поле введення;
HTMLTextAreaElement — багаторядкове поле;
HTMLFormElement — форма;
HTMLSelectElement — список вибору;
HTMLDivElement — div.
Не слід використовувати Event або MouseEvent із глобального DOM API для React-обробника:
// Неправильно для React-обробника
const handleClick = (event: MouseEvent) => {
console.log(event.currentTarget);
};Потрібно імпортувати тип із React:
import type { MouseEvent } from "react";
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
console.log(event.currentTarget);
};Тип має відповідати елементу:
import type { ChangeEvent } from "react";
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
console.log(event.currentTarget.value);
};
function Example() {
return <textarea onChange={handleChange} />;
}У цьому прикладі тип неправильний, бо обробник використовується для textarea. Правильний варіант:
import type { ChangeEvent } from "react";
const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
console.log(event.currentTarget.value);
};value у checkboxДля прапорця потрібно використовувати checked:
import type { ChangeEvent } from "react";
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const isChecked = event.currentTarget.checked;
console.log(isChecked);
};preventDefaultЯкщо форма не повинна перезавантажувати сторінку, у onSubmit потрібно викликати:
event.preventDefault();anyНе варто вимикати перевірку типів:
const handleChange = (event: any) => {
console.log(event.currentTarget.value);
};Тип any приховує помилки. Краще вказати конкретний тип події та HTML-елемента.
Для кліків використовуйте MouseEvent.
Для введення в input і textarea — ChangeEvent.
Для надсилання форм — FormEvent.
Для клавіатурних дій — KeyboardEvent.
Для фокусу — FocusEvent.
Після типу події вказуйте HTML-елемент: HTMLInputElement, HTMLButtonElement тощо.
Для значення елемента зазвичай використовуйте event.currentTarget.
Для checkbox читайте event.currentTarget.checked.
У onSubmit використовуйте event.preventDefault(), якщо не потрібне стандартне перезавантаження сторінки.
Не замінюйте точні типи подій на any.