Когда использовать Ref, а когда — State
Выбор между useRef и useState определяется одной простой идеей: нужно ли, чтобы изменение значения вызывало перерисовку компонента?
Используйте useState, если…
Значение влияет на то, что пользователь видит. Например:
- Текст в поле ввода, который отображается где-то ещё
- Состояние кнопки (активна/неактивна)
- Выбранная вкладка или тема интерфейса
- Список задач, фильтры, ошибки валидации
const [count, setCount] = useState(0);
// При setCount(1) компонент перерисуется — это необходимо,
// если, например, вы показываете "Счётчик: 1"
useState — основной инструмент для управления данными, которые определяют внешний вид приложения.
Используйте useRef, если…
Значение нужно только для логики, но не влияет на отображение. Например:
- Ссылка на DOM-элемент (для фокуса, прокрутки, измерения)
- Хранение предыдущего значения пропса или состояния
- Идентификатор таймера (
setTimeout,setInterval) - Кэш дорогих вычислений
- Счётчик попыток, логирование, технические данные
const timerIdRef = useRef(null);
// Изменение timerIdRef.current не должно перерисовывать UI —
// оно нужно только для остановки таймера позже
Практическое правило
Если вы используете значение внутри JSX (
{value}), — это состояние.
Если вы используете значение только в функциях, эффектах или обработчиках, — это ref.
Пример выбора в формах
- Контролируемая форма:
useState— потому что вы можете показывать ошибку, кнопку активировать/деактивировать, делать предпросмотр. - Неконтролируемая форма:
useRef— если вы просто читаете данные при отправке и ничего не отображаете на основе ввода.
Ошибки при выборе
- Использовать
refдля данных в JSX — компонент не обновится, даже если значение изменилось. - Использовать
stateдля таймеров или DOM-ссылок — это вызовет лишние ререндеры и усложнит код.
В подавляющем большинстве случаев начинайте с useState. Переходите к useRef только тогда, когда убедитесь, что перерисовка не нужна и мешает производительности или логике.