Класичний спосіб - onSubmit:
function SearchForm() {
function handleSubmit(e) {
e.preventDefault(); // інакше браузер перезавантажить сторінку
const data = new FormData(e.currentTarget);
search(data.get('q'));
}
return (
<form onSubmit={handleSubmit}>
<input name="q" />
<button type="submit">Шукати</button>
</form>
);
}
React 19 - функція в пропі action:
function SearchForm() {
async function searchAction(formData) {
await search(formData.get('q'));
}
return (
<form action={searchAction}>
<input name="q" />
<button type="submit">Шукати</button>
</form>
);
}
Чим action відрізняється:
preventDefault()не потрібен - React сам перехоплює відправку;- функція отримує
FormDataодразу аргументом; - виконується всередині Transition - на ній працюють
useFormStatus(стан відправки для кнопки),useActionState(результат дії) іuseOptimistic; - після успішного виконання неконтрольовані поля форми скидаються автоматично. Якщо поле має лишитися заповненим (пошук), значення треба зберігати в стані чи повертати з дії;
- метод HTTP завжди POST, незалежно від атрибута
method; - різні кнопки можуть викликати різні дії через
formAction:
<button type="submit">Опублікувати</button>
<button formAction={saveDraft}>Зберегти чернетку</button>
Коли все ж onSubmit: складна клієнтська валідація перед відправкою, бібліотеки форм зі своїм handleSubmit (React Hook Form), потреба повністю контролювати процес.
Пастка для обох способів: кнопка без type усередині форми - це type="submit". Кнопка «Скасувати» чи «Додати рядок» без type="button" відправить форму.