Комментарии (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)}
/>
);
}