Ответ
useRef — это хук в React, который создает мутабельный (изменяемый) объект с свойством current. Он сохраняет значение между рендерами, но не вызывает ререндер при изменении.
Основные случаи использования:
- Доступ к DOM-элементам
const inputRef = useRef(null);
<input ref={inputRef} />;
// inputRef.current.focus();
- Хранение мутабельных значений (например, таймеров, предыдущих значений)
const intervalId = useRef();
intervalId.current = setInterval(...);
// clearInterval(intervalId.current);
Отличие от useState:
- Изменение
ref.currentне триггерит ререндер. - Значение
refсохраняется на протяжении всего времени жизни компонента.
⚠️ Не используйте ref для значений, которые должны влиять на UI — для этого подходит useState.
Ответ 18+ 🔞
Давай разберём эту штуку, useRef, а то многие её как будто боятся, как чёрт ладана. Представь себе такую картину: у тебя есть коробка. Не простая, а волшебная, блядь. Ты кладёшь в неё что угодно — хоть таймер, хоть ссылку на инпут, хоть фотку своей бывшей. И эта хуйня там лежит, тихо, мирно, между всеми этими рендерами, которые React как сумасшедший гоняет туда-сюда.
Вот эта коробка — и есть useRef. У неё есть одно-единственное свойство — current. Туда всё и кладётся.
Зачем это, спрашивается, нахуй?
Ну, во-первых, достучаться до реального DOM-элемента. Ты ж в виртуальном мире React живёшь, а иногда надо реальный инпот фокуснуть, или размеры дива узнать. Вот как это делается:
const myInputRef = useRef(null); // Создал коробку, пока пустую
// Вешаю эту коробку-ссылку на инпут
return <input ref={myInputRef} type="text" />;
// А потом, где надо, достаю из коробки сам инпут и делаю с ним что хочу
// myInputRef.current.focus(); // Щас тебя сфокусу, сука!
Во-вторых, хранить какую-то изменяемую хуйню, которая не должна рендеры вызывать. Классика — ID таймера или интервала.
const timerId = useRef(); // Опять коробка. Пустая.
// Запускаю интервал и кладу его айдишник в коробку
timerId.current = setInterval(() => {
console.log('Тик-так, ёпта!');
}, 1000);
// Когда надо будет это остановить — просто достану айди из коробки
// clearInterval(timerId.current);
А теперь самое важное, блядь! Чем это отличается от useState?
Давай на пальцах. useState — это как громкая связь. Как только значение меняется — весь компонент орет: «ААА, всё поменялось, давайте всё перерисовывать, сука!». Ре-рендер, обновление интерфейса.
А useRef — это полная тишина, под ковром. Ты меняешь ref.current на что угодно — хоть на пингвина в пальто, компоненту похуй. Он не перерисовывается. Значение просто тихонько лежит в своей коробке и ждёт своего часа.
Итог простой, как три копейки:
- Нужно что-то показать в интерфейсе и чтобы оно менялось →
useState. - Нужно что-то спрятать и хранить (айдишники, DOM-элементы, предыдущее значение), чтобы не дергать лишние рендеры →
useRef.
Запомни эту разницу, а то потом будешь, как Герасим, смотреть на утопленную Муму и говорить «Мууу...», потому что нихуя не понял, где что использовать.