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

Если сохранить inpput в useRef, будет ли он считаться контроллируемым

2.2 Middle🔥 281 комментариев

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

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

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

useRef для Input: Контролируемый или нет?

Короткий ответ

Нет, не будет контролируемым. Если вы сохраняете input в useRef, это остаётся неконтролируемым компонентом. Контролируемость зависит от того, кто управляет значением value — React состояние или DOM.

Контролируемый vs Неконтролируемый

Контролируемый (Controlled)

React управляет значением через state:

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

Характеристики:

  • Значение хранится в React состоянии
  • React отрисовывает компонент заново при изменении
  • Можно легко валидировать, трансформировать
  • Синхронизация между состоянием и DOM гарантирована

Неконтролируемый (Uncontrolled)

DOM управляет своим значением, React только читает:

function UncontrolledInput() {
  const inputRef = useRef(null);
  
  const handleSubmit = () => {
    console.log(inputRef.current.value); // Читаем из DOM
  };
  
  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleSubmit}>Submit</button>
    </>
  );
}

Характеристики:

  • Значение хранится в DOM, не в React
  • useRef просто создаёт ссылку на DOM элемент
  • React НЕ перерисовывает при изменении
  • Нет синхронизации React state и DOM

Примеры: useRef вариант

function RefExample() {
  const inputRef = useRef(null);
  
  // Это НЕКОНТРОЛИРУЕМЫЙ input
  return (
    <>
      <input ref={inputRef} defaultValue="Initial" />
      <button onClick={() => alert(inputRef.current.value)}>
        Read Value
      </button>
    </>
  );
}

// Даже если вы сохраняете значение в useRef
const inputValue = useRef('');
inputValue.current = 'something'; // Это не подвязано к input!

<input ref={inputRef} /> // Это всё равно неконтролируемый

Почему это важно

Проблема: попытка контролировать через useRef

// ПЛОХО: смешивание подходов
function BadExample() {
  const valueRef = useRef('');
  const inputRef = useRef(null);
  
  const handleChange = () => {
    valueRef.current = inputRef.current.value; // Только читаем
  };
  
  // Нельзя перерисовать input снаружи
  const setInputValue = (newValue) => {
    valueRef.current = newValue;
    // inputRef.current.value = newValue; // Приходится манипулировать DOM!
  };
  
  return <input ref={inputRef} onChange={handleChange} />;
}

Правильно: контролируемый компонент

function GoodExample() {
  const [value, setValue] = useState('');
  
  return (
    <>
      <input
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
      <button onClick={() => setValue('')}>Clear</button>
    </>
  );
}

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

Используйте контролируемый (useState)

  • Нужна валидация в реальном времени
  • Нужно изменить значение программно
  • Зависимости от других полей (например, если поле A заполнено, очистить B)
  • Нужно вычислять производные данные
function Form() {
  const [email, setEmail] = useState('');
  const [errors, setErrors] = useState('');
  
  const handleChange = (e) => {
    const value = e.target.value;
    setEmail(value);
    
    // Валидация в реальном времени
    if (!value.includes('@')) {
      setErrors('Invalid email');
    } else {
      setErrors('');
    }
  };
  
  return (
    <>
      <input value={email} onChange={handleChange} />
      {errors && <span>{errors}</span>}
    </>
  );
}

Используйте неконтролируемый (useRef)

  • Нужно просто прочитать значение при сабмите
  • Интеграция с не-React кодом
  • Фокус/блюр события
  • Файловые input
function FileInput() {
  const fileRef = useRef(null);
  
  const handleUpload = () => {
    const file = fileRef.current.files[0];
    console.log(file);
  };
  
  return (
    <>
      <input ref={fileRef} type="file" />
      <button onClick={handleUpload}>Upload</button>
    </>
  );
}

function FocusInput() {
  const inputRef = useRef(null);
  
  return (
    <>
      <input ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>
        Focus
      </button>
    </>
  );
}

Рекомендация

По умолчанию используйте контролируемые компоненты (useState). Переходите на useRef только если есть конкретная причина:

// 1. Контролируемый (по умолчанию)
const [value, setValue] = useState('');
<input value={value} onChange={(e) => setValue(e.target.value)} />

// 2. Если нужно только читать — неконтролируемый
const ref = useRef(null);
<input ref={ref} defaultValue="" />
const value = ref.current.value; // При необходимости

Заключение

useRef не делает input контролируемым. Контролируемость определяется тем, управляет ли React значением через state. useRef просто создаёт ссылку на DOM элемент, не влияя на тип управления.