Ограничения и рекомендации

Хотя useRef — мощный инструмент, его неправильное использование может привести к трудноуловимым ошибкам и нарушению принципов React. Вот ключевые ограничения и рекомендации.

Не мутируйте ref во время рендера

Изменение ref.current внутри тела компонента (не в эффектах или обработчиках) нарушает чистоту рендера:

// Плохо
function BadComponent() {
  const ref = useRef(0);
  ref.current = ref.current + 1; // мутирует при каждом рендере
  return <div>{ref.current}</div>;
}

Это приводит к непредсказуемому поведению, особенно при использовании строгого режима или будущих асинхронных рендереров.

Правильно — обновлять ref.current только в useEffect, обработчиках событий или колбэках.

Не используйте ref вместо состояния для данных, влияющих на UI

Если значение должно отображаться в интерфейсе или влиять на то, что пользователь видит, используйте useState:

// Избегайте
const countRef = useRef(0);
// ...и где-то: countRef.current += 1
// но в JSX: {countRef.current} — это работает, но нарушает реактивность

// Правильно
const [count, setCount] = useState(0);

React не будет знать, что нужно обновить компонент, если вы измените только ref.

Избегайте прямого манипулирования DOM без необходимости

React построен на декларативной модели: вы описываете, как должен выглядеть интерфейс, а не как его изменить. Прямое изменение DOM через ref:

  • Ломает предсказуемость
  • Усложняет тестирование
  • Может конфликтовать с обновлениями React

Используйте ref только тогда, когда нет другого способа: фокус, измерение размеров, работа с медиа, интеграция со сторонними библиотеками.

Ref не работает напрямую с функциональными компонентами

Если вы попытаетесь передать ref в обычный функциональный компонент, React проигнорирует его:

// Не сработает
function MyInput() {
  return <input />;
}
// ...
<MyInput ref={myRef} /> // myRef.current будет null

Чтобы исправить, используйте forwardRef:

// 
const MyInput = forwardRef((props, ref) => {
  return <input ref={ref} {...props} />;
});

Итог

  • Используйте ref только для задач, которые невозможно решить через state и props.
  • Обновляйте ref.current вне фазы рендера.
  • Предпочитайте управляемые компоненты (useState + onChange) неконтролируемым (ref + value), если нет веской причины.
  • Помните: React — про данные, а не про DOM. Ref — исключение, а не правило.