Важность отображения сообщений об ошибках
Мы добрались до одной из самых любимых (и ненавидимых) тем фронтенд-разработчиков — отображение сообщений об ошибках в формах. Если бы у разработчиков был тотем, связанный с пользовательским опытом, то это были бы осмысленные и понятные сообщения об ошибках. Ведь от того, как вы их покажете, зависит не только UX, но и количество пользователей, которые не бросят вашу форму на полпути из-за недоумения или ярости.
Сегодня мы поговорим о том, как использовать библиотеки Formik и Yup для создания удобных и информативных сообщений об ошибках в формах. Давайте начнем с вопроса: почему мы вообще паримся с сообщениями об ошибках?
Представьте, что вы пришли в магазин, а консультант вместо помощи молча смотрит на вас, когда вы пытаетесь выбрать что-то. Без подсказок сложно понять, что делать дальше, верно? То же самое и с формами.
Что делает хорошее сообщение об ошибке:
- Понятность. Пользователь должен сразу понять, что пошло не так и как это исправить.
- Контекст. Сообщение должно быть привязано к конкретному полю (а не абстрактное «что-то пошло не так»).
- Чёткое место. Сообщение должно отображаться рядом с полем, чтобы не заставлять пользователя искать его.
- Мгновенная обратная связь. Если ошибка исправлена — сообщение исчезает сразу.
Пример неправильного UX:
Пользователь вводит данные, нажимает «Отправить», а вы выдаёте один и тот же баннер: «Ошибка! Попробуйте снова». Позиция «гуляй, Вася!» в разработке, верно?
Пример формы
Чтобы продемонстрировать отображение ошибок, создадим простую форму для регистрации. Она будет включать следующие поля:
- Email. Должен быть валидным адресом.
- Password. Минимум 6 символов.
- Confirm Password. Должен совпадать с полем Password.
Начнем с базового шаблона:
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
// Схема валидации с Yup
const validationSchema = Yup.object({
email: Yup.string()
.email("Некорректный Email")
.required("Поле Email обязательно"),
password: Yup.string()
.min(6, "Минимальная длина пароля — 6 символов")
.required("Поле Пароль обязательно"),
confirmPassword: Yup.string()
.oneOf([Yup.ref("password")], "Пароли должны совпадать")
.required("Поле Подтверждения пароля обязательно"),
});
const RegistrationForm: React.FC = () => {
return (
<Formik
initialValues={{ email: "", password: "", confirmPassword: "" }}
validationSchema={validationSchema}
onSubmit={(values) => {
console.log("Submitted values:", values);
}}
>
{({ handleSubmit, isSubmitting }) => (
<Form onSubmit={handleSubmit}>
<div>
<label>Email</label>
<Field name="email" type="email" />
<ErrorMessage name="email" component="div" className="error" />
</div>
<div>
<label>Пароль</label>
<Field name="password" type="password" />
<ErrorMessage name="password" component="div" className="error" />
</div>
<div>
<label>Подтвердите пароль</label>
<Field name="confirmPassword" type="password" />
<ErrorMessage
name="confirmPassword"
component="div"
className="error"
/>
</div>
<button type="submit" disabled={isSubmitting}>
Отправить
</button>
</Form>
)}
</Formik>
);
};
export default RegistrationForm;
Что здесь происходит:
- Мы используем
Formikдля управления состоянием формы. - Схема валидации создается через
Yup(параметры валидности и сообщения об ошибках настраиваются здесь). - Компонент
ErrorMessageотвечает за отображение ошибок. Он автоматически связывается с указаннымFieldчерез имя поля.
Кастомизация сообщений об ошибках
Конечно, ErrorMessage из коробки просто работает, но это скучно, и мы, как настоящие разработчики, любим кастомизацию. Давайте создадим более кастомный способ отображения ошибок:
const ErrorText: React.FC<{ message: string }> = ({ message }) => (
<div style={{ color: "red", fontSize: "14px" }}>{message}</div>
);
Теперь используем это в нашей форме:
<ErrorMessage name="email">
{(msg) => <ErrorText message={msg} />}
</ErrorMessage>
Этот подход позволяет нам использовать однотипный стиль для всех ошибок. И да, никто не запрещает добавлять сюда иконки, анимации и всё, что сделает ваш UX космическим.
Реальная обратная связь: подсветка полей с ошибками
Ошибки — это не только текст, который нужно отобразить, но и визуальная подсказка, например, подсветка полей с проблемами. Удобно, когда пользователь сразу видит, что не так.
<Field
name="email"
type="email"
className={`input ${errors.email && touched.email ? "input-error" : ""}`}
/>
И добавим CSS:
.input-error {
border: 1px solid red;
background-color: #ffe5e5;
}
Теперь каждое поле с ошибкой будет выделяться красным.
Отображение ошибок на уровне формы
Иногда ошибки нужно показывать не только для конкретного поля, но и для всей формы целиком. Например, если пользователь не прошёл капчу или сервер вернул ошибку. Formik поддерживает это через status и специальное свойство setStatus.
<Formik
initialValues={{ email: "", password: "", confirmPassword: "" }}
validationSchema={validationSchema}
onSubmit={(values, { setStatus }) => {
// Симулируем ошибку от сервера
if (values.email === "test@test.com") {
setStatus("Этот Email уже зарегистрирован");
} else {
console.log("Submitted values:", values);
}
}}
>
{({ handleSubmit, status }) => (
<Form onSubmit={handleSubmit}>
{status && <div className="form-error">{status}</div>}
{/* Остальные поля формы */}
</Form>
)}
</Formik>
CSS для ошибки формы:
.form-error {
color: red;
font-size: 16px;
margin-bottom: 10px;
}
Типичные ошибки при работе с сообщениями об ошибках
Когда вы работаете с формами, ошибки неизбежны, и я говорю не об ошибках в данных, а о наших — разработческих. Вот самые частые проблемы:
- Вы забыли указать
nameдляFieldилиErrorMessage. Formik не сможет связать ошибки с полями, и ничего не будет отображаться. - Использование
if-elseвнутри схем валидации Yup может стать громоздким. Лучше разбивать правила на отдельные функции/методы. - Игнорирование UX-подходов — например, не убирать сообщение об ошибке, когда пользователь всё исправил.
Теперь ваши формы будут понятными, дружелюбными и помогут пользователям быстро находить и исправлять ошибки. Форма без ошибок — это не только задача фронтендеров, но и мечта пользователей.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ