Как обратиться к DOM из React?
Основы React
Прямой доступ к DOM из React нужен редко (обычно всё решается декларативно), но когда нужен — правильный путь один: ref.
useRef + атрибут ref
const VideoPlayer = ({ src }) => {
const videoRef = useRef(null);
const handlePlay = () => {
videoRef.current.play(); // императивный вызов DOM API
};
return (
<>
<video ref={videoRef} src={src} />
<button onClick={handlePlay}>▶</button>
</>
);
};После коммита React кладёт DOM-узел в videoRef.current (до первого коммита там null; при размонтировании — снова null).
Когда DOM-доступ оправдан
- Фокус, выделение текста:
inputRef.current.focus(). - Измерения:
getBoundingClientRect(), scrollHeight — для позиционирования, виртуализации. - Скролл:
scrollIntoView(). - Медиа: play/pause у video/audio.
- Интеграция с не-React библиотеками (карты, чарты, редакторы) — им отдают контейнер.
Дополнительные механизмы
- Callback ref — функция вместо объекта: вызывается при присоединении/отсоединении узла; удобно для измерений в момент появления.
- Ref на компонент — до React 19 через forwardRef; наружу можно отдать ограниченный API через useImperativeHandle (
{ focus, reset }). - В классах — createRef.
Чего избегать
document.querySelectorв компонентах — обход React, ломается при нескольких экземплярах и в тестах.- Ручные мутации управляемых React узлов (innerHTML, изменение атрибутов) — React перезапишет их при следующем рендере.
- Чтение/запись ref во время рендера — только в эффектах и обработчиках.
Коротко для собеседования
DOM из React достаётся через useRef + атрибут ref (в узле появляется после коммита); использовать для фокуса, измерений, скролла, медиа и интеграций. Не querySelector и не ручные мутации React-управляемых узлов. Для доступа к узлам ребёнка — forwardRef/useImperativeHandle (в React 19 ref — обычный проп).