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

Как обработать форму с неуправляемыми компонентами?

2.0 Middle🔥 141 комментариев
#React

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

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

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

Обработка форм с неуправляемыми компонентами в React

Неуправляемые компоненты (uncontrolled components) - это компоненты, которые хранят своё состояние в DOM, а не в React state. Это альтернатива управляемым компонентам (controlled components), где состояние полностью контролируется React.

Различие между управляемыми и неуправляемыми компонентами

Управляемый компонент - React контролирует значение:

function ControlledForm() {
  const [email, setEmail] = useState('');
  
  return (
    <input 
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  );
}

Неуправляемый компонент - значение хранится в DOM:

function UncontrolledForm() {
  const emailRef = useRef(null);
  
  return (
    <input ref={emailRef} />
  );
}

Как обработать неуправляемую форму

1. Использование useRef для доступа к значению

import { useRef } from 'react';

function ContactForm() {
  const nameRef = useRef(null);
  const emailRef = useRef(null);
  const messageRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    
    // Извлекаем значения из DOM через ref
    const formData = {
      name: nameRef.current.value,
      email: emailRef.current.value,
      message: messageRef.current.value
    };
    
    console.log('Form data:', formData);
    // Отправляем на сервер
    submitForm(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input ref={nameRef} type="text" placeholder="Ваше имя" required />
      <input ref={emailRef} type="email" placeholder="Email" required />
      <textarea ref={messageRef} placeholder="Сообщение" required />
      <button type="submit">Отправить</button>
    </form>
  );
}

2. Использование FormData API

FormData - современный способ работы с неуправляемыми формами:

function AdvancedForm() {
  const formRef = useRef(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    // Создаём FormData из формы
    const formData = new FormData(formRef.current);
    
    // Можно работать с данными напрямую
    const data = Object.fromEntries(formData);
    console.log(data);
    
    // Или отправить напрямую на сервер
    const response = await fetch('/api/submit', {
      method: 'POST',
      body: formData // FormData автоматически установит Content-Type
    });
  };

  return (
    <form ref={formRef} onSubmit={handleSubmit}>
      <input name="username" type="text" required />
      <input name="password" type="password" required />
      <select name="country">
        <option>Россия</option>
        <option>США</option>
      </select>
      <button type="submit">Отправить</button>
    </form>
  );
}

3. Обработка файлов в неуправляемых формах

function FileUploadForm() {
  const fileRef = useRef(null);
  const [uploadProgress, setUploadProgress] = useState(0);

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    const file = fileRef.current.files[0];
    if (!file) return;

    const formData = new FormData();
    formData.append('file', file);

    const xhr = new XMLHttpRequest();
    
    xhr.upload.addEventListener('progress', (e) => {
      if (e.lengthComputable) {
        const percentComplete = (e.loaded / e.total) * 100;
        setUploadProgress(percentComplete);
      }
    });

    xhr.addEventListener('load', () => {
      console.log('File uploaded successfully');
      setUploadProgress(0);
    });

    xhr.open('POST', '/api/upload');
    xhr.send(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input ref={fileRef} type="file" required />
      {uploadProgress > 0 && <progress value={uploadProgress} max="100" />}
      <button type="submit">Загрузить</button>
    </form>
  );
}

Гибридный подход: Неуправляемое хранилище + React контроль

Иногда нужен баланс между неуправляемыми и управляемыми компонентами:

function HybridForm() {
  const formRef = useRef(null);
  const [isSubmitting, setIsSubmitting] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsSubmitting(true);

    try {
      const formData = new FormData(formRef.current);
      const response = await fetch('/api/form', {
        method: 'POST',
        body: formData
      });

      if (response.ok) {
        // Очищаем форму после успешной отправки
        formRef.current.reset();
        alert('Форма успешно отправлена');
      }
    } catch (error) {
      console.error('Form submission failed:', error);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <form ref={formRef} onSubmit={handleSubmit}>
      <input name="email" type="email" placeholder="Email" required />
      <textarea name="feedback" placeholder="Ваш отзыв" required />
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Отправка...' : 'Отправить'}
      </button>
    </form>
  );
}

Когда использовать неуправляемые компоненты?

  1. Простые формы - когда мало валидации
  2. Интеграция с другим кодом - jQuery плагины, vanilla JS
  3. Файловые загрузки - input type="file" лучше как неуправляемый
  4. Работа с FormData - для сложных многосекционных форм
  5. Производительность - огромные формы с сотнями полей

Когда использовать управляемые компоненты?

  1. Валидация в реальном времени - нужен контроль значения
  2. Условное отображение - значение влияет на UI
  3. Динамические значения - заполнение из API
  4. Интеграция с Redux/MobX - синхронизация состояния
  5. Комплексные взаимодействия - поля зависят друг от друга

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

Как обработать форму с неуправляемыми компонентами? | PrepBro