


useRef возвращает объект с полем current, который сохраняется между рендерами компонента. Изменение current не запускает новый рендер. Поэтому ref подходит для ссылки на DOM-элемент и служебных значений, от которых не зависит отображаемый интерфейс. Для видимого текста, счётчика или состояния кнопки обычно нужен useState.
В примере Mentoring.digital кнопка переводит фокус в поле поиска. Она не отправляет форму и не выполняет сетевой запрос.
import { useRef } from "react";
export default function SearchField() {
const inputRef = useRef(null);
function focusSearch() {
inputRef.current?.focus();
}
return (
<div>
<label htmlFor="search-query">Поисковый запрос</label>
<input id="search-query" ref={inputRef} />
<button type="button" onClick={focusSearch}>
Перейти к поиску
</button>
</div>
);
}
React запишет DOM-узел в inputRef.current после его добавления в интерфейс. До этого значение равно null. При удалении узла React снова установит null. Необязательная цепочка ?. защищает вызов, если элемента уже нет.
Тип кнопки указан явно, чтобы при переносе примера внутрь формы она случайно не стала кнопкой отправки. Метка через htmlFor остаётся связана с полем. Фокус должен быть заметен пользователю клавиатуры, поэтому не убирайте стандартную обводку без равноценного видимого оформления.
import { useRef, useState } from "react";
export default function ClickTracker() {
const lastClickAt = useRef(null);
const [count, setCount] = useState(0);
function handleClick() {
lastClickAt.current = Date.now();
setCount(value => value + 1);
}
return <button onClick={handleClick}>Нажатий: {count}</button>;
}
Число на кнопке хранится в state, потому что его изменение должно отобразиться. Время последнего нажатия хранится в ref как служебная информация. В этом примере оно не выводится. Если нужно показывать время в интерфейсе, перенесите его в состояние или другую подходящую модель отображения.
Обычная локальная переменная создаётся заново при каждом вызове функции компонента. Ref сохраняет своё поле между рендерами. Переменная вне компонента, в свою очередь, может оказаться общей для нескольких экземпляров. Выбор ref позволяет хранить отдельное служебное значение у каждого экземпляра.
Чтение DOM и вызов focus() выполняйте в обработчике события или подходящем эффекте. Не делайте это прямо во время рендера. React должен иметь возможность вычислять интерфейс без таких побочных действий. Аналогично не используйте изменение ref во время рендера как скрытый счётчик вызовов компонента.
В Strict Mode разработческая проверка может вызвать функцию компонента дважды, причём один из созданных ref-объектов будет отброшен. Это не означает два пользовательских нажатия. Проверять обработчик нужно реальным действием, а не числом вызовов тела компонента.
Для дальнейшей практики подойдут курсы React. Если ref появился как обход сложного состояния, полезно разобрать компонент с ментором по React.