← Назад к вопросам

Перерендерится ли компонент при изменении current в ref

2.0 Middle🔥 171 комментариев
#React

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Перерендер компонента при изменении current в ref

Это важный вопрос, касающийся внутренней работы React и его механизма рендеринга. Ответ — нет, изменение значения свойства current объекта ref напрямую не вызывает перерендер компонента.

Объяснение механизма ref в React

Ref (реф) в React — это специальный объект, предназначенный для хранения мутирующих значений, которые могут изменяться между рендерами, но их изменение не должно запускать новый рендер. Он выступает как "лазейка" для прямого взаимодействия с DOM-элементами или для сохранения любого мутируемого значения, которое должно жить между рендерами.

Объект ref создается с помощью хука useRef и имеет следующую структуру:

const myRef = useRef(initialValue);
// myRef = { current: initialValue }

Ключевое свойство — current. Изменение его значения происходит напрямую, как в обычном объекте:

myRef.current = newValue; // Прямое присваивание

Почему перерендер не происходит?

React отслеживает изменения только в состояниях (state) и пропсах (props), чтобы определить необходимость перерендера компонента. Это основа его реактивной модели. Механизм ref был сознательно разработан так, чтобы его изменения обходили этот реактивный цикл:

  1. useRef возвращает один и тот же объект при каждом рендере. Хук useRef создает объект при первом рендере и возвращает тот же самый (по ссылке) объект при всех последующих рендерах. Изменение его внутреннего свойства current не создает новый объект.
  2. React не сравнивает содержимое current. React не проводит глубокого сравнения объектов ref между рендерами. Он лишь проверяет, что ссылка на сам объект ref осталась неизменной (она всегда неизменна).
  3. ref — это мутируемый контейнер. Его основная задача — хранить значение, которое может меняться без уведомления React. Это аналогично переменной класса в компонентах-классах.

Пример для демонстрации

Рассмотрим компонент с ref и state:

import React, { useRef, useState } from 'react';

function DemoComponent() {
  const counterRef = useRef(0);
  const [stateCounter, setStateCounter] = useState(0);

  const updateRef = () => {
    // Изменяем ref напрямую - перерендера НЕ будет
    counterRef.current = counterRef.current + 1;
    console.log('Ref current:', counterRef.current);
  };

  const updateState = () => {
    // Изменяем state - перерендер БУДЕТ
    setStateCounter(stateCounter + 1);
  };

  console.log('Компонент рендерится');

  return (
    <div>
      <p>State Counter: {stateCounter}</p>
      <p>Ref Counter (не отображается автоматически): {counterRef.current}</p>
      <button onClick={updateRef}>Увеличить Ref</button>
      <button onClick={updateState}>Увеличить State</button>
    </div>
  );
}

В этом примере:

  • Нажатие на "Увеличить Ref" обновляет counterRef.current, но компонент не перерендерится. Значение в DOM ({counterRef.current}) останется старым, так как React не знает об изменении.
  • Нажатие на "Увеличить State" вызывает перерендер, и во время этого нового рендера компонент "увидит" последнее значение counterRef.current (так как объект ref сохранился) и отобразит его.

Когда изменение ref.current может косвенно вызвать перерендер?

Перерендер может произойти, если изменение ref.current является частью логики, которая в конечном итоге изменяет состояние (state):

const intervalRef = useRef();
const [isActive, setIsActive] = useState(false);

const startInterval = () => {
  // Изменяем ref
  intervalRef.current = setInterval(() => {
    // Логика внутри интервала изменяет state
    setIsActive(prev => !prev); // Это вызывает перерендер
  }, 1000);
};

Ключевые выводы и практические следствия

  • ref предназначен для "нереактивных" данных: DOM элементов, экземпляров классов, таймеров, идентификаторов и других значений, которые должны сохраняться между рендерами без их запуска.
  • Если нужно реактивное обновление UI, используйте state. Значения, которые должны автоматически отображаться в интерфейсе при их изменении, всегда должны быть в состоянии.
  • Значение ref.current можно использовать при рендере, но оно будет "фиксироваться" на момент последнего рендера. Чтобы увидеть его актуальное значение в UI, изменение ref должно сопровождаться изменением state, которое вызовет новый рендер.
  • Прямое манипулирование DOM через ref — это классический случай, когда изменение current (например, вызов методов на DOM элементе) не должно и не вызывает перерендера.

Таким образом, изменение current в ref — это операция вне реактивного цикла React. Она не запускает перерендер, что делает ref мощным инструментом для работы с мутирующими данными, которые не должны быть частью реактивного потока данных компонента.