Ограничения и рекомендации
Хотя 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 — исключение, а не правило.