Валидация на клиенте и сервере

Валидация данных — ключевой элемент построения надежных веб-приложений. Она позволяет предотвращать некорректный ввод на клиентской стороне и защищает сервер от потенциально опасных или ошибочных данных. В Preact, как и в других реактивных фреймворках, валидация тесно интегрирована с компонентной архитектурой и состоянием приложения.

Управление состоянием формы

Форма в Preact строится с использованием контролируемых компонентов. Основная идея заключается в том, что состояние каждого поля формы хранится в объекте состояния компонента:

import { h } from 'preact';
import { useState } from 'preact/hooks';

function LoginForm() {
  const [formData, setFormData] = useState({ email: '', password: '' });
  const [errors, setErrors] = useState({});

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });
  };

  return (
    <form>
      <input
        type="email"
        name="email"
        value={formData.email}
        onIn put={handleChange}
      />
      {errors.email && <span>{errors.email}</span>}
      <input
        type="password"
        name="password"
        value={formData.password}
        onIn put={handleChange}
      />
      {errors.password && <span>{errors.password}</span>}
    </form>
  );
}

Ключевой момент — использование onInput вместо onChange, что обеспечивает немедленное обновление состояния при каждом вводе символа.

Клиентская валидация

Клиентская валидация выполняется до отправки данных на сервер. Она позволяет пользователю получать мгновенную обратную связь. В Preact она реализуется через функции проверки и обновление состояния ошибок:

const validate = (data) => {
  const errors = {};
  if (!data.email.includes('@')) errors.email = 'Некорректный email';
  if (data.password.length < 6) errors.password = 'Пароль слишком короткий';
  return errors;
};

const handleSubmit = (e) => {
  e.preventDefault();
  const validationErrors = validate(formData);
  setErrors(validationErrors);
  if (Object.keys(validationErrors).length === 0) {
    // Данные готовы к отправке на сервер
  }
};

Выделение функции validate позволяет использовать одну и ту же логику для нескольких компонентов или форм, повышая повторное использование кода.

Асинхронная валидация

Иногда требуется проверка данных на сервере перед отправкой, например, уникальность логина или email. В Preact это выполняется с использованием асинхронных функций и эффектов:

import { useEffect } from 'preact/hooks';

const checkEmailUnique = async (email) => {
  const response = await fetch(`/api/check-email?email=${email}`);
  const { unique } = await response.json();
  return unique;
};

useEffect(() => {
  if (formData.email) {
    checkEmailUnique(formData.email).then((unique) => {
      setErrors((prev) => ({ ...prev, email: unique ? '' : 'Email уже занят' }));
    });
  }
}, [formData.email]);

Эффект срабатывает при изменении email, обеспечивая мгновенную обратную связь пользователю.

Серверная валидация

Клиентская валидация не исключает необходимости проверки на сервере. Серверная валидация гарантирует корректность данных и безопасность приложения. В Node.js и Express это может выглядеть следующим образом:

import express from 'express';
import bodyParser from 'body-parser';
import { body, validationResult } from 'express-validator';

const app = express();
app.use(bodyParser.json());

app.post('/register', [
  body('email').isEmail().withMessage('Некорректный email'),
  body('password').isLength({ min: 6 }).withMessage('Пароль слишком короткий')
], (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  // Сохранение пользователя
  res.status(200).json({ message: 'Регистрация успешна' });
});

Использование библиотеки express-validator упрощает создание правил валидации и возврат подробных сообщений об ошибках.

Обработка ошибок и UX

Правильная валидация — это не только проверка данных, но и удобная подача ошибок пользователю:

  • Вывод сообщений рядом с полем ввода.
  • Использование цветовой индикации и иконок ошибок.
  • Анимация появления сообщений для привлечения внимания.
  • Асинхронная проверка уникальности данных без блокировки формы.

Интеграция клиентской и серверной валидации

Оптимальный подход — комбинирование двух уровней валидации. Клиент проверяет базовые правила (формат email, длина пароля), сервер — более строгие и безопасные проверки (уникальность, корректность данных, права доступа). В Preact данные можно отправлять через fetch или axios и обрабатывать ответы сервера, обновляя состояние ошибок:

const submitToServer = async () => {
  const response = await fetch('/register', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(formData)
  });
  const result = await response.json();
  if (response.status !== 200) {
    const serverErrors = {};
    result.errors.forEach(err => serverErrors[err.param] = err.msg);
    setErrors(serverErrors);
  }
};

Такой подход обеспечивает безопасное и удобное взаимодействие пользователя с формой, минимизируя количество некорректных данных на сервере.

Резюме ключевых принципов

  • Контролируемые компоненты и состояние формы позволяют отслеживать ввод в реальном времени.
  • Клиентская валидация обеспечивает мгновенную обратную связь и улучшает UX.
  • Асинхронная проверка на уникальность данных повышает интерактивность.
  • Серверная валидация обязательна для безопасности и надежности приложения.
  • Обработка ошибок должна быть визуально понятной и информативной.

Эти принципы формируют основу безопасной и удобной работы с данными в Preact, обеспечивая согласованность между клиентской и серверной частью приложения.