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

Что такое неуправляемый компонент в React?

1.6 Junior🔥 161 комментариев
#React

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Неуправляемый компонент — компонент, управляемый DOM

Неуправляемый компонент (Uncontrolled Component) — это React компонент, значение которого управляется не React, а непосредственно DOM. React не контролирует состояние input поля, checkbox или select, а просто отрисовывает их и предоставляет доступ к DOM через refs.

Управляемые vs Неуправляемые компоненты

// ❌ Управляемый компонент (Controlled)
function ControlledInput() {
  const [value, setValue] = useState("");

  return (
    <input
      value={value} // React контролирует значение
      onChange={(e) => setValue(e.target.value)}
      placeholder="Введи текст"
    />
  );
}

// ✅ Неуправляемый компонент (Uncontrolled)
function UncontrolledInput() {
  const inputRef = useRef<HTMLInputElement>(null);

  const handleSubmit = () => {
    // Берём значение из DOM через ref
    console.log("Введённое значение:", inputRef.current?.value);
  };

  return (
    <>
      <input
        ref={inputRef}
        placeholder="Введи текст"
        defaultValue="Начальное значение"
      />
      <button onClick={handleSubmit}>Отправить</button>
    </>
  );
}

Ключевые различия

АспектУправляемыйНеуправляемый
ЗначениеВ React stateВ DOM
ИзменениеonChange + setStateПрямой доступ к DOM
СинхронизацияДвусторонняя привязкаНет
ПроизводительностьМедленнее (на каждое изменение перерисовка)Быстрее (нет перерисовки)
ИспользованиеРекомендуетсяРедко

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

// 1. Интеграция с библиотеками, не написанными на React
function JQueryIntegration() {
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (containerRef.current) {
      // jQuery код работает напрямую с DOM
      $(containerRef.current).datepicker();
    }
  }, []);

  return <div ref={containerRef} />;
}

// 2. Быстрая загрузка больших форм (много полей)
function LargeForm() {
  const formRef = useRef<HTMLFormElement>(null);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    // Собираем все данные формы напрямую из DOM
    const formData = new FormData(formRef.current!);
    const values = Object.fromEntries(formData);

    console.log("Данные формы:", values);
  };

  return (
    <form ref={formRef} onSubmit={handleSubmit}>
      <input name="firstName" type="text" />
      <input name="lastName" type="text" />
      <input name="email" type="email" />
      {/* ... ещё 100 полей */}
      <button type="submit">Отправить</button>
    </form>
  );
}

// 3. Воспроизведение видео/аудио
function VideoPlayer() {
  const videoRef = useRef<HTMLVideoElement>(null);

  const handlePlay = () => {
    videoRef.current?.play();
  };

  const handlePause = () => {
    videoRef.current?.pause();
  };

  return (
    <>
      <video ref={videoRef} width="400">
        <source src="video.mp4" type="video/mp4" />
      </video>
      <button onClick={handlePlay}>Воспроизвести</button>
      <button onClick={handlePause}>Пауза</button>
    </>
  );
}

// 4. Работа с файлами
function FileUpload() {
  const fileInputRef = useRef<HTMLInputElement>(null);

  const handleClick = () => {
    fileInputRef.current?.click();
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      console.log("Выбранный файл:", file.name);
    }
  };

  return (
    <>
      <button onClick={handleClick}>Выбрать файл</button>
      <input
        ref={fileInputRef}
        type="file"
        onChange={handleFileChange}
        style={{ display: "none" }}
      />
    </>
  );
}

Использование с форм-валидацией

function LoginForm() {
  const emailRef = useRef<HTMLInputElement>(null);
  const passwordRef = useRef<HTMLInputElement>(null);
  const [errors, setErrors] = useState<Record<string, string>>({});

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    // Валидация на основе значений из DOM
    const newErrors: Record<string, string> = {};

    const email = emailRef.current?.value;
    const password = passwordRef.current?.value;

    if (!email || !email.includes("@")) {
      newErrors.email = "Некорректный email";
    }
    if (!password || password.length < 6) {
      newErrors.password = "Пароль должен быть минимум 6 символов";
    }

    if (Object.keys(newErrors).length > 0) {
      setErrors(newErrors);
      return;
    }

    console.log("Отправляем на сервер:", { email, password });
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <input
          ref={emailRef}
          type="email"
          placeholder="Email"
          defaultValue=""
        />
        {errors.email && <span>{errors.email}</span>}
      </div>

      <div>
        <input
          ref={passwordRef}
          type="password"
          placeholder="Пароль"
          defaultValue=""
        />
        {errors.password && <span>{errors.password}</span>}
      </div>

      <button type="submit">Войти</button>
    </form>
  );
}

Важные замечания

  • defaultValue и defaultChecked — устанавливают начальное значение неуправляемого компонента
  • Не используй value и onChange для неуправляемых компонентов
  • Неуправляемые компоненты сложнее тестировать
  • В большинстве случаев управляемые компоненты — лучший выбор
  • Ref переживает несколько renders, но сам компонент может быть перемонтирован
// ❌ Неправильно: смешиваем управляемый и неуправляемый
function BadComponent() {
  const [value, setValue] = useState("");
  const inputRef = useRef<HTMLInputElement>(null);

  return (
    <input
      ref={inputRef}
      value={value} // Конфликт!
      onChange={(e) => setValue(e.target.value)}
    />
  );
}
Что такое неуправляемый компонент в React? | PrepBro