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

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

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

Комментарии (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 элемент, не влияя на тип управления.

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