В чем разница между useState и useRef?
Хуки
Оба хука сохраняют значение между рендерами, но ведут себя противоположно: useState вызывает перерендер, useRef — нет.
Отличия
- Реакция на изменение:
setStateпланирует перерендер; запись вref.currentне вызывает ничего — React о ней не знает. - Момент обновления: state обновляется асинхронно, к следующему рендеру;
ref.currentменяется синхронно и сразу читается. - Назначение: state — данные, которые видит пользователь; ref — «служебная» память компонента и доступ к DOM.
- Стабильность: сам объект ref (
{ current }) один на всё время жизни компонента; значение state — своё в каждом рендере (замыкание).
Пример, показывающий разницу
const Demo = () => {
const [count, setCount] = useState(0); // отображается — state
const clicksRef = useRef(0); // просто считаем — ref
const handleClick = () => {
clicksRef.current += 1; // UI не обновится
setCount(count + 1); // UI обновится
};
return <button onClick={handleClick}>{count}</button>;
};Когда что выбирать
- useState: всё, что влияет на рендер — текст инпута, флаги открытия, данные списка.
- useRef: DOM-элементы (фокус, измерения), id таймеров, WebSocket-инстансы, предыдущие значения props, флаг «уже смонтирован», любые данные, изменение которых не должно перерисовывать компонент.
Частая ошибка
Хранить в state то, что не отображается (например, id интервала), — лишние перерендеры. И наоборот: хранить в ref отображаемые данные — UI перестаёт обновляться.
Коротко для собеседования
useState — реактивное состояние: обновление асинхронное и вызывает перерендер. useRef — мутируемый контейнер { current }: обновление синхронное и рендер не триггерит. Правило: влияет на то, что видит пользователь, — state; служебное значение или DOM-узел — ref.