← Назад к вопросам

Как относишься к обновлению React по работе с формами?

1.7 Middle🔥 132 комментариев
#React#Архитектура и паттерны

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Моё мнение об обновлении React и работе с формами

Вопрос о работе с формами в React — это сложная и постоянно эволюционирующая тема. С каждым обновлением React появляются новые возможности и новые паттерны работы с формами. Дам развёрнутое мнение, основанное на практическом опыте.

Развитие подхода к формам в React

React 16 и ранее: Controlled Components

В ранних версиях React доминировал паттерн управляемых компонентов (controlled components):

// Классический подход
class LoginForm extends React.Component {
  state = { email: '', password: '' };

  handleEmailChange = (e) => {
    this.setState({ email: e.target.value });
  };

  handlePasswordChange = (e) => {
    this.setState({ password: e.target.value });
  };

  handleSubmit = () => {
    console.log(this.state);
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          value={this.state.email}
          onChange={this.handleEmailChange}
        />
        <input
          type="password"
          value={this.state.password}
          onChange={this.handlePasswordChange}
        />
        <button type="submit">Login</button>
      </form>
    );
  }
}

Этот подход был надёжным, но повторяющимся (DRY нарушается). Для больших форм кода становилось очень много.

React Hooks: useReducer и useState

С приходом Hooks разработка форм стала проще благодаря функциональным компонентам:

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

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

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        name="email"
        value={formData.email}
        onChange={handleChange}
      />
      <input
        name="password"
        type="password"
        value={formData.password}
        onChange={handleChange}
      />
      <button type="submit">Login</button>
    </form>
  );
}

Это улучшение, но всё ещё есть повторяющийся код для каждого input.

React 19: Действия (Actions) и useActionState

Реакт 19 привнёс экспериментальный подход с Server Actions и useActionState, который значительно упрощает работу с формами:

// Серверная функция (например, в Next.js)
async function submitLoginForm(formData) {
  const email = formData.get('email');
  const password = formData.get('password');
  
  // Валидация и обработка
  const result = await authenticateUser(email, password);
  return result;
}

// Клиентский компонент (React 19)
function LoginForm() {
  const [state, formAction, isPending] = useActionState(
    submitLoginForm,
    null
  );

  return (
    <form action={formAction}>
      <input type="email" name="email" required />
      <input type="password" name="password" required />
      <button type="submit" disabled={isPending}>
        {isPending ? 'Logging in...' : 'Login'}
      </button>
      {state?.error && <p>{state.error}</p>}
    </form>
  );
}

Моё мнение о разных подходах

1. Управляемые компоненты (Controlled Components)

Плюсы:

  • Полный контроль над состоянием
  • Легко валидировать и трансформировать данные
  • Предсказуемое поведение
  • Хорошо работает с комплексной логикой

Минусы:

  • Много boilerplate кода
  • Нарушает DRY принцип для больших форм
  • Может быть медленнее на очень больших формах (много re-renders)

Когда использовать:

  • Формы с комплексной валидацией
  • Когда нужны зависимые поля
  • Когда требуется real-time feedback

2. Неуправляемые компоненты (Uncontrolled Components)

function LoginForm() {
  const emailRef = useRef(null);
  const passwordRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log({
      email: emailRef.current.value,
      password: passwordRef.current.value
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" ref={emailRef} />
      <input type="password" ref={passwordRef} />
      <button type="submit">Login</button>
    </form>
  );
}

Плюсы:

  • Меньше кода
  • Быстрее для простых форм
  • Ближе к традиционному HTML

Минусы:

  • Нет контроля над состоянием
  • Сложнее валидировать
  • Нельзя реагировать на изменения в real-time

Мнение: используйте редко, только для очень простых форм.

3. Библиотеки управления формами (React Hook Form, Formik)

import { useForm } from 'react-hook-form';

function LoginForm() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        {...register('email', {
          required: 'Email required',
          pattern: {
            value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
            message: 'Invalid email'
          }
        })}
      />
      {errors.email && <p>{errors.email.message}</p>}
      
      <input
        type="password"
        {...register('password', {
          required: 'Password required',
          minLength: {
            value: 8,
            message: 'Min 8 chars'
          }
        })}
      />
      {errors.password && <p>{errors.password.message}</p>}
      
      <button type="submit">Login</button>
    </form>
  );
}

Плюсы:

  • Минимум boilerplate кода
  • Встроенная валидация
  • Хорошая производительность
  • Большое сообщество
  • React Hook Form очень лёгкая

Минусы:

  • Ещё одна зависимость
  • Curve обучения
  • Может быть избыточна для простых форм

Мнение: React Hook Form — отличный выбор для production приложений.

Что мне нравится в React 19

Плюсы нового подхода

  1. Меньше client-side логики — валидация может происходить на сервере
  2. Progressive Enhancement — формы работают без JavaScript
  3. Простота — меньше состояния на клиенте
  4. Безопасность — чувствительная валидация на сервере

Минусы нового подхода

  1. Зависимость от фреймворка — нужен Next.js или подобное
  2. Сложнее локальная валидация — все ещё требуется handleChange
  3. Новые паттерны — нужно переучиваться
  4. Нет широкой поддержки — многие хосты не поддерживают Server Actions

Моя рекомендация

Для простых форм (2-3 поля)

// Используй управляемые компоненты
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

Для средних форм (5-10 полей)

// Используй React Hook Form
import { useForm } from 'react-hook-form';

Для больших, комплексных форм (50+ полей)

// Используй React Hook Form + Zod для схемы валидации
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

Для современных Next.js приложений

// React 19 + Server Actions
const [state, formAction] = useActionState(serverAction, null);

Лучшие практики 2025

1. Валидация на обе стороны

// Клиент: быстрый feedback
const { register, formState: { errors } } = useForm({
  resolver: zodResolver(schema)
});

// Сервер: безопасность
async function submitForm(formData) {
  const validated = schema.parse(formData);
  // Обработка...
}

2. Используй Zod/Yup для схем

const schema = z.object({
  email: z.string().email('Invalid email'),
  password: z.string().min(8, 'Min 8 chars'),
  confirmPassword: z.string()
}).refine((data) => data.password === data.confirmPassword, {
  message: 'Passwords do not match',
  path: ['confirmPassword']
});

3. Обрабатывай ошибки вежливо

const handleError = (error) => {
  if (error.code === 'AUTH_FAILED') {
    return 'Invalid email or password';
  }
  if (error.code === 'NETWORK_ERROR') {
    return 'Network error. Please try again';
  }
  return 'Something went wrong';
};

Заключение

Моё мнение: React Hook Form + Zod — золотой стандарт на сегодняшний день. Это оптимальный баланс между:

  • Простотой разработки
  • Производительностью
  • Гибкостью
  • Экосистемой

React 19 с Server Actions — интересный шаг, но пока не все хосты его поддерживают, и требуется Next.js или аналог. Когда он будет более распространён, это может стать стандартом.

Главное правило: выбирайте инструмент в зависимости от размера и сложности формы. Не усложняйте простые формы и не недооценивайте большие.