Отправка формы
onSubmit
Форма обрабатывается через onSubmit. Это позволяет нажать Enter в любом поле и вызвать отправку.
function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
console.log({ email, password });
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit">Войти</button>
</form>
);
}
e.preventDefault() обязателен — иначе браузер перезагрузит страницу.
Кнопка submit
<button type="submit">Отправить</button>
Если type не указан — в форме кнопка по умолчанию submit.
Отправка на сервер
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
const res = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
if (res.ok) {
// успех
} else {
// ошибка
}
}
Состояние отправки
const [isSubmitting, setIsSubmitting] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setIsSubmitting(true);
try {
await fetch('/api/login', { ... });
} finally {
setIsSubmitting(false);
}
}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Отправка...' : 'Войти'}
</button>
Обработка ошибок
const [error, setError] = useState('');
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setError('');
const res = await fetch('/api/login', { ... });
if (!res.ok) {
const data = await res.json();
setError(data.message ?? 'Ошибка');
return;
}
// успех
}
{error && <p className="error">{error}</p>}
Сброс после отправки
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
await fetch('/api/posts', { ... });
setTitle('');
setBody('');
}
Или через form.reset():
const formRef = useRef<HTMLFormElement>(null);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
await fetch('/api/posts', { ... });
formRef.current?.reset();
}
Несколько кнопок
Если в форме несколько кнопок — укажи type:
<form onSubmit={handleSubmit}>
<input value={title} onChange={(e) => setTitle(e.target.value)} />
<button type="submit">Сохранить</button>
<button type="button" onClick={handleCancel}>Отмена</button>
<button type="reset">Очистить</button>
</form>
submit— отправляет формуbutton— обычная кнопка, не отправляетreset— сбрасывает значения
Валидация перед отправкой
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!email.includes('@')) {
setError('Некорректный email');
return;
}
if (password.length < 8) {
setError('Пароль слишком короткий');
return;
}
// отправка
}
Отправка FormData
Если используешь FormData:
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
const formData = new FormData(e.currentTarget as HTMLFormElement);
await fetch('/api/upload', {
method: 'POST',
body: formData,
});
}
fetch сам установит Content-Type: multipart/form-data.
Двойная отправка
Защита от двойного клика:
<button type="submit" disabled={isSubmitting}>Отправить</button>
Или проверка в обработчике:
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (isSubmitting) return;
setIsSubmitting(true);
// ...
}
Итоги
onSubmit+preventDefault- Кнопка
type="submit" - Состояние
isSubmittingдля индикатора - Обработка ошибок
form.reset()для сбросаtype="button"для обычных кнопок внутри формы