Форма: от HTML и JavaScript к React
Собираем значения полей и подключаем обработчик отправки.
On this page
Для Next.js 16.3.8 (App Router) и React 19.3.0, Zod 4.6.5. Обновлено .
Форма собирает значения полей и запускает действие после отправки. Начнем с обычного HTML, затем подключим JavaScript и перенесем поведение в React. Серверную проверку добавим в следующей статье.
Что делает сам HTML
<form action="/register" method="post">
<label for="name">Имя</label>
<input id="name" name="name" autocomplete="name" required />
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email" required />
<button type="submit">Отправить</button>
</form>labelсвязан с полем черезforиid. Подпись можно нажать; она помогает и программам чтения с экрана.nameзадает ключ передаваемого значения.idне заменяет его.actionзадает адрес получателя. Здесь/register– условный адрес; обработчик ещё не создан.method="post"передает значения в теле запроса. Сам по себе POST не шифрует данные: за защиту соединения отвечает HTTPS.requiredиtype="email"включают проверку браузера.type="submit"отправляет форму, в том числе через Enter из поля.
placeholder дает подсказку внутри поля, но исчезает при вводе. Он не заменяет постоянную подпись.
JavaScript читает значения
Чтобы проверить чтение данных без сервера, добавьте предыдущей форме id="registration", уберите action и добавьте под ней <p id="result" role="status"></p>. Подключите этот скрипт через <script src="main.js" defer></script>:
const form = document.querySelector("#registration");
const result = document.querySelector("#result");
form.addEventListener("submit", (event) => {
event.preventDefault();
const data = new FormData(form);
const name = data.get("name");
const email = data.get("email");
result.textContent = `Прочитали: ${name}, ${email}. На сервер ничего не отправлено.`;
});Обработчик submit подключается к форме. Поэтому обработчик сработает и при отправке через Enter. preventDefault() отменяет обычную отправку и переход по адресу. Он не отправляет данные сам.
FormData собирает значения полей с name. Поля с disabled не передаются. Флажок checkbox без галочки тоже не попадает в данные. Метод get возвращает строку, файл или null, если ключа нет.
То же поведение в React
В учебном проекте создайте отдельную страницу. Для описания аргумента обработчика импортируем тип события:
"use client";
import { useState, type SubmitEvent } from "react";
export default function RegisterPage() {
const [message, setMessage] = useState("");
function handleSubmit(event: SubmitEvent<HTMLFormElement>) {
event.preventDefault();
const data = new FormData(event.currentTarget);
const name = data.get("name");
const email = data.get("email");
if (typeof name !== "string" || typeof email !== "string") {
setMessage("Не удалось прочитать поля формы.");
return;
}
setMessage(`Прочитали: ${name}, ${email}. На сервер ничего не отправлено.`);
}
return (
<main>
<h1>Заявка на мероприятие</h1>
<form onSubmit={handleSubmit}>
<label htmlFor="name">Имя</label>
<input id="name" name="name" autoComplete="name" required />
<label htmlFor="email">Email</label>
<input
id="email"
name="email"
type="email"
autoComplete="email"
required
/>
<button type="submit">Отправить</button>
</form>
<p role="status">{message}</p>
</main>
);
}currentTarget – форма, к которой привязан обработчик. В JSX for записывается как htmlFor, autocomplete – как autoComplete. Обработчик передается функцией через onSubmit.
Откройте /register, заполните поля и отправьте форму кнопкой, затем Enter. Проверьте неверный email. Сейчас сообщение показывает только то, что значения прочитаны.
Кто хранит введенный текст
В показанной форме текущее значение хранит сам HTML-элемент. Это неуправляемое поле. defaultValue может задавать начальное значение, а FormData читает его при отправке.
Если текст нужен React прямо при вводе, поле делают управляемым:
const [name, setName] = useState("");
<input
name="name"
value={name}
onChange={(event) => setName(event.target.value)}
/>;value берется из состояния, onChange обновляет его. Без обновления состояния React будет возвращать прежний текст, и поле окажется недоступным для редактирования. Не переключайте одно поле между undefined и строкой: для текста используйте начальное "".
Управляемое поле удобно, если нужно сразу показывать введенный текст в превью, менять другие поля при вводе или управлять сбросом формы. Если значения нужны только при отправке, не обязательно создавать отдельный useState для каждого поля.
Почему проверки браузера недостаточно
Пользователь может изменить HTML в DevTools или отправить запрос собственной программой. Поэтому сервер повторно проверяет данные. Пример следующей статьи примет имя, email, дату мероприятия и необязательный комментарий.
Документация: HTML-форма, FormData, input в React, form в React.