Валидация формы
Валидация проверяет данные до отправки на сервер. Бывает на лету (при вводе) и при отправке.
Валидация при отправке
function Form() {
const [email, setEmail] = useState('');
const [error, setError] = useState('');
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!email.includes('@')) {
setError('Введите корректный email');
return;
}
setError('');
// отправка
}
return (
<form onSubmit={handleSubmit}>
<input value={email} onChange={(e) => setEmail(e.target.value)} />
{error && <p className="error">{error}</p>}
<button>Отправить</button>
</form>
);
}
Валидация на лету
function Form() {
const [email, setEmail] = useState('');
const isValid = email === '' || email.includes('@');
return (
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
className={isValid ? '' : 'invalid'}
/>
);
}
Пустая строка считается валидной — ошибка появляется только когда пользователь начал вводить.
Валидация при потере фокуса
const [email, setEmail] = useState('');
const [touched, setTouched] = useState(false);
const isValid = email.includes('@');
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
onBlur={() => setTouched(true)}
/>
{touched && !isValid && <p className="error">Некорректный email</p>}
touched показывает, что пользователь уже взаимодействовал с полем.
Несколько полей
const [values, setValues] = useState({ email: '', password: '' });
const [errors, setErrors] = useState<Record<string, string>>({});
function validate() {
const newErrors: Record<string, string> = {};
if (!values.email.includes('@')) {
newErrors.email = 'Некорректный email';
}
if (values.password.length < 8) {
newErrors.password = 'Пароль должен быть минимум 8 символов';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
}
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!validate()) return;
// отправка
}
Отображение ошибок
<input
name="email"
value={values.email}
onChange={handleChange}
onBlur={validate}
/>
{errors.email && <p className="error">{errors.email}</p>}
Встроенная HTML-валидация
Браузер умеет валидировать сам:
<form>
<input type="email" required />
<input type="text" minLength={3} maxLength={20} />
<input type="number" min={0} max={100} />
<input type="text" pattern="[A-Za-z]+" />
</form>
Атрибуты: required, min, max, minLength, maxLength, pattern, type.
Для кастомного сообщения:
<input
required
onInvalid={(e) => (e.target as HTMLInputElement).setCustomValidity('Введи email')}
onInput={(e) => (e.target as HTMLInputElement).setCustomValidity('')}
/>
Преимущества JS-валидации
- Сообщения на русском
- Полный контроль над UX
- Асинхронные проверки (занят ли email)
- Валидация на сервере дублируется
Серверная валидация
const [serverError, setServerError] = useState('');
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
const res = await fetch('/api/register', {
method: 'POST',
body: JSON.stringify(values),
});
if (!res.ok) {
const data = await res.json();
setServerError(data.message);
return;
}
}
Серверная валидация обязательна — клиентскую можно обойти.
Итоги
- Валидация при отправке и на лету
touchedпоказывает взаимодействие- Объект
errorsдля нескольких полей - HTML-валидация даёт базу
- JS-валидация — контроль и локализация
- Серверная валидация — обязательна