Что использовал для валидации на прошлых местах работы?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Инструменты валидации в разных проектах
На протяжении 10+ лет я использовал различные подходы к валидации в зависимости от требований проекта, стека технологий и эволюции инструментов. Расскажу о наиболее значимых решениях.
Ранний период (2010-2015): базовая валидация
Собственные функции валидации
// Простой подход: писали валидацию сами
function validateEmail(email) {
const regex = /^[^@]+@[^@]+\.[^@]+$/;
return regex.test(email);
}
function validateRequired(value) {
return value && value.trim() !== '';
}
function validateForm(formData) {
const errors = {};
if (!validateRequired(formData.name)) errors.name = "Name is required";
if (!validateEmail(formData.email)) errors.email = "Invalid email";
return Object.keys(errors).length === 0 ? null : errors;
}
Этот подход работал для небольших проектов, но быстро становился неудобным при масштабировании.
jQuery эра (2012-2018): jQuery Validation
jQuery Validation Plugin
// Популярный в то время подход
$("#myForm").validate({
rules: {
name: "required",
email: {
required: true,
email: true
},
age: {
required: true,
number: true,
min: 18
}
},
messages: {
name: "Name is required",
email: "Please enter valid email",
age: "Age must be at least 18"
},
submitHandler: function(form) {
// Отправить форму
}
});
Преимущества: просто, быстро, встроено. Недостатки: жёстко связано с jQuery, не типизировано.
Angular эра (2015-2019): Reactive Forms Validators
Angular встроенные валидаторы
import { FormBuilder, Validators } from '@angular/forms';
this.form = this.fb.group({
name: ['', [Validators.required, Validators.minLength(3)]],
email: ['', [Validators.required, Validators.email]],
age: ['', [Validators.required, Validators.min(18)]],
website: ['', [Validators.pattern(/^https?:\/\/.+/)]]
});
function passwordStrengthValidator(control) {
const value = control.value;
if (!value) return null;
const hasNumber = /[0-9]/.test(value);
const hasUpper = /[A-Z]/.test(value);
const hasSymbol = /[!@#$%^&*]/.test(value);
const passwordValid = hasNumber && hasUpper && hasSymbol;
return passwordValid ? null : { weakPassword: true };
}
Это было лучше: типизировано, переиспользуемо, но специфично для Angular.
React эра (2017-2019): Formik
Formik - самая популярная библиотека
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
const validationSchema = Yup.object().shape({
name: Yup.string()
.required('Name is required')
.min(3, 'Name must be at least 3 characters'),
email: Yup.string()
.email('Invalid email')
.required('Email is required'),
age: Yup.number()
.required('Age is required')
.min(18, 'Must be at least 18'),
password: Yup.string()
.required('Password is required')
.min(8, 'Password must be at least 8 characters')
.matches(/[A-Z]/, 'Must contain uppercase')
.matches(/[0-9]/, 'Must contain number')
});
export function MyForm() {
return (
<Formik
initialValues={{ name: '', email: '', age: '', password: '' }}
validationSchema={validationSchema}
onSubmit={(values) => {
console.log(values);
}}
>
{({ errors, touched }) => (
<Form>
<Field name="email" type="email" />
<ErrorMessage name="email" />
</Form>
)}
</Formik>
);
}
Formik был идеален для React: управление состоянием, валидация и обработка ошибок в одном месте.
Современный период (2020-2026): React Hook Form + Zod
React Hook Form стал стандартом
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const userSchema = z.object({
name: z.string()
.min(3, 'Name must be at least 3 characters')
.max(50, 'Name must not exceed 50 characters'),
email: z.string()
.email('Invalid email address'),
age: z.number()
.int('Age must be integer')
.min(18, 'Must be at least 18')
.max(120, 'Invalid age'),
password: z.string()
.min(8, 'Password must be at least 8 characters')
.regex(/[A-Z]/, 'Must contain uppercase')
.regex(/[0-9]/, 'Must contain number')
});
type User = z.infer<typeof userSchema>;
export function UserForm() {
const { register, handleSubmit, formState: { errors } } = useForm<User>({
resolver: zodResolver(userSchema)
});
return (
<form onSubmit={handleSubmit((data) => {
console.log(data);
})}>
<input {...register('email')} />
{errors.email && <span>{errors.email.message}</span>}
<button type="submit">Submit</button>
</form>
);
}
Преимущества React Hook Form: минимальный overhead, отличная производительность, интеграция с Zod для типобезопасности, поддержка async валидации.
Валидация на бэкенде
Важный принцип: ВСЕГДА валидируй на обеих сторонах
const emailValid = /^[^@]+@[^@]+\.[^@]+$/.test(email);
if (!emailValid) showError("Invalid email");
// На бэкенде (Python + Pydantic):
from pydantic import BaseModel, EmailStr, validator
class UserCreate(BaseModel):
email: EmailStr
name: str
age: int
Асинхронная валидация
Важно для проверки уникальности (email, username)
const userSchema = z.object({
email: z.string()
.email()
.refine(
async (email) => {
const response = await fetch(`/api/check-email?email=${email}`);
const { available } = await response.json();
return available;
},
{ message: "Email already in use" }
)
});
Мои предпочтения сегодня
- Zod для валидации - типобезопасно, минимальные зависимости
- React Hook Form - минимальный overhead
- HTML5 constraints для базовой валидации
- Реальная валидация на бэкенде - никогда не доверяй фронтенду
- Асинхронная валидация только когда необходимо
Резюме
Валидация эволюционировала от простых проверок к типобезопасным, структурированным подходам. Сегодня стандарт - это React Hook Form + Zod, которые обеспечивают оптимальный баланс между DX и производительностью. Главный принцип: всегда валидируй на обеих сторонах (фронтенд для UX, бэкенд для безопасности).