> В чем разница между хранением массива в useState и useRef в React (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Домклик, Софт Медиа Групп

Стек: React

> Пример ответа

Короткий ответ

Основная разница в том, что useState вызывает ререндер компонента при изменении значения, а useRef - нет. useRef хранит мутабельное значение, которое сохраняется между рендерами, но не влияет на жизненный цикл компонента. useState же предназначен для данных, изменения которых должны отражаться в UI. Также useRef возвращает объект с свойством .current, а useState - кортеж [value, setValue].

Подробное объяснение

useState и useRef - это хуки React, которые сохраняют данные между рендерами компонента, но с разными целями и поведением.

useState:

  • Создаёт реактивное состояние, изменение которого триггерит ререндер компонента
  • Возвращает текущее значение и функцию-сеттер для его обновления
  • Значение иммутабельно - React сравнивает предыдущее и новое значение
  • Используется для данных, отображаемых в UI (текст, флаги, списки)

useRef:

  • Создаёт мутабельный объект с свойством .current, который сохраняется между рендерами
  • Изменение .current не вызывает ререндер
  • Значение можно менять напрямую (ref.current = newValue)
  • Используется для ссылок на DOM-элементы, хранения предыдущих значений, таймеров, анимаций

Ключевое отличие: useState - для реактивных данных, useRef - для данных, не влияющих на отображение.

На практике

В реальных проектах выбор между хуками зависит от сценария:

  • useState - когда изменение данных должно обновлять интерфейс: формы, списки, модальные окна, состояния загрузки
  • useRef - когда нужно хранить данные, не связанные с рендером: идентификаторы таймеров, предыдущие пропсы, ссылки на DOM для фокуса или измерения размеров, экземпляры сторонних библиотек

Типичный пример: если вы храните в useRef значение, которое нужно отобразить на экране, UI не обновится - это частая ошибка. И наоборот, использование useState для данных, которые не влияют на UI, приведёт к лишним ререндерам и снижению производительности.

Пример кода

JSX
import { useState, useRef, useEffect } from 'react';
function TimerComponent() {
// useState для отображаемого значения
const [seconds, setSeconds] = useState(0);
// useRef для хранения ID таймера (не влияет на UI)
const timerRef = useRef(null);
const startTimer = () => {
timerRef.current = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
};
const stopTimer = () => {
clearInterval(timerRef.current);
timerRef.current = null;
};
// useRef для хранения предыдущего значения
const prevSecondsRef = useRef(seconds);
useEffect(() => {
prevSecondsRef.current = seconds;
}, [seconds]);
return (
<div>
<p>Текущее: {seconds}, Предыдущее: {prevSecondsRef.current}</p>
<button onClick={startTimer}>Старт</button>
<button onClick={stopTimer}>Стоп</button>
</div>
);
}

Как отвечать на собеседовании

Начните с ключевого отличия: ререндер vs отсутствие ререндера. Затем объясните, что оба хука сохраняют данные между рендерами, но useState реактивен, а useRef - нет. Приведите конкретные примеры использования: для useRef - DOM-ссылки, таймеры, предыдущие значения; для useState - данные, отображаемые в UI. Упомяните, что useRef мутабелен, а useState требует сеттер для изменения. Если спросят про производительность, объясните, что useRef не вызывает лишних ререндеров, но его изменения не видны в UI.

Что проверяет интервьюер

Интервьюер оценивает понимание жизненного цикла React-компонента, различие между реактивными и нереактивными данными, умение выбирать правильный инструмент под задачу. Также проверяется знание того, как работают ререндеры и как избежать лишних обновлений. Для senior-уровня важно показать понимание trade-off: useRef эффективнее по производительности, но не подходит для данных, влияющих на отображение.

Типичные ошибки

  • Использование useRef для данных, которые должны обновлять UI - интерфейс не перерисуется
  • Использование useState для хранения ссылок на DOM или таймеров - лишние ререндеры
  • Попытка напрямую мутировать состояние из useState (state.value = newValue) - React не обнаружит изменения
  • Забывание, что useRef возвращает объект, а не значение - нужно обращаться через .current
  • Использование useRef для хранения предыдущего значения без useEffect - значение не будет обновляться после рендера

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью