Что такое hook useRef

Ответ

useRef — это хук в React, который создает мутабельный (изменяемый) объект с свойством current. Он сохраняет значение между рендерами, но не вызывает ререндер при изменении.

Основные случаи использования:

  1. Доступ к DOM-элементам
const inputRef = useRef(null);
<input ref={inputRef} />;
// inputRef.current.focus();
  1. Хранение мутабельных значений (например, таймеров, предыдущих значений)
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.

Запомни эту разницу, а то потом будешь, как Герасим, смотреть на утопленную Муму и говорить «Мууу...», потому что нихуя не понял, где что использовать.