useRef — это хук в Preact, предназначенный для хранения
изменяемого значения, которое не вызывает повторного рендеринга при
изменении. Основное его применение — работа с DOM элементами
напрямую, когда требуется получить доступ к их свойствам или
методам.
Для создания ссылки на DOM элемент используется хук
useRef:
import { h } from 'preact';
import { useRef, useEffect } from 'preact/hooks';
function InputFocus() {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return <input ref={inputRef} type="text" />;
}
В этом примере inputRef хранит ссылку на
<input>. После монтирования компонента через
useEffect выполняется доступ к свойству
current, которое указывает на DOM элемент, и вызывается
метод focus().
Ключевой момент: useRef возвращает
объект с единственным свойством current. Ссылка сохраняется
между рендерами, что делает её идеальной для работы с DOM напрямую.
В отличие от состояния (useState), изменение значения
current не инициирует повторный рендер.
Это позволяет безопасно хранить объекты DOM или любые изменяемые данные
без влияния на визуальное обновление компонента.
function Timer() {
const intervalRef = useRef(null);
const [count, setCount] = useState(0);
useEffect(() => {
intervalRef.current = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(intervalRef.current);
}, []);
return <div>{count}</div>;
}
Здесь intervalRef используется для хранения
идентификатора таймера. Это демонстрирует, как useRef
подходит для хранения объектов, которые должны быть доступны между
рендерами, но не влияют на UI напрямую.
С помощью ref можно:
offsetWidth,
getBoundingClientRect());scrollIntoView(), play(),
pause() для медиаконтента).Пример измерения размеров элемента:
function BoxSize() {
const boxRef = useRef(null);
const [size, setSize] = useState({ width: 0, height: 0 });
useEffect(() => {
if (boxRef.current) {
const { offsetWidth, offsetHeight } = boxRef.current;
setSize({ width: offsetWidth, height: offsetHeight });
}
}, []);
return (
<div>
<div ref={boxRef} style={{ width: 200, height: 100, background: 'lightblue' }}></div>
<p>Ширина: {size.width}px, Высота: {size.height}px</p>
</div>
);
}
В этом примере через boxRef.current получаем размеры
блока и сохраняем их в состоянии для отображения.
useRef может быть использован для доступа не только к
обычным DOM элементам, но и к компонентам Preact, если
они реализованы с помощью forwardRef. Это открывает
возможности вызова методов дочерних компонентов.
import { forwardRef, useImperativeHandle } from 'preact/hooks';
const Child = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
sayHello: () => console.log('Привет из дочернего компонента')
}));
return <div>Дочерний компонент</div>;
});
function Parent() {
const childRef = useRef();
return (
<div>
<Child ref={childRef} />
<button onCl ick={() => childRef.current.sayHello()}>Вызвать метод</button>
</div>
);
}
Важно: useImperativeHandle позволяет
контролировать, какие методы и свойства будут доступны через
ref, скрывая внутреннюю реализацию компонента.
ref для работы с DOM, когда
необходим прямой доступ к элементу или его
методам.ref для хранения состояния, которое
влияет на рендер. Для этого предназначен useState.refs для управления списком элементов.function List() {
const itemsRef = useRef([]);
const scrollToItem = index => {
itemsRef.current[index]?.scrollIntoView({ beh * avior: 'smooth' });
};
return (
<div>
{['A', 'B', 'C'].map((item, index) => (
<div
key={index}
ref={el => (itemsRef.current[index] = el)}
style={{ padding: '10px', border: '1px solid black', margin: '5px' }}
>
{item}
</div>
))}
<button onCl ick={() => scrollToItem(2)}>Прокрутить к C</button>
</div>
);
}
Такой подход удобен для работы со списками элементов и управления их поведением напрямую через DOM.
useRef является мощным инструментом Preact для
управления DOM и сохранения изменяемых объектов между рендерами,
обеспечивая гибкий контроль над элементами интерфейса без лишних
повторных отрисовок.