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

Когда в React ререндерится компонент?

1.8 Middle🔥 231 комментариев
#React

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

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

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

Когда происходит ререндер компонента в React?

Ререндер (re-render) — это процесс, при котором React заново вычисляет и обновляет вывод компонента. Важно понимать, что ререндер не всегда означает фактическое обновление DOM (этот процесс называется reconciliation). React может вычислить новый виртуальный DOM и сравнить его с предыдущим, но внести в реальный DOM только минимально необходимые изменения.

Основные триггеры ререндера

1. Изменение состояния (State Change)

Наиболее частая причина. При вызове функции обновления состояния (например, setState в классовых компонентах или useState/useReducer в функциональных) React помечает компонент как нуждающийся в ререндере.

function Counter() {
  const [count, setCount] = useState(0); // Изначальное состояние

  const increment = () => {
    setCount(count + 1); // Вызов setCount запускает ререндер
  };

  return (
    <div>
      <p>Счёт: {count}</p>
      <button onClick={increment}>Увеличить</button>
    </div>
  );
}

2. Изменение пропсов (Props Change)

Когда родительский компонент передаёт новые пропсы дочернему компоненту, дочерний компонент ререндерится.

function ParentComponent() {
  const [value, setValue] = useState('');

  return (
    <div>
      <input onChange={(e) => setValue(e.target.value)} />
      <ChildComponent text={value} /> {/* ChildComponent ререндерится при каждом изменении value */}
    </div>
  );
}

function ChildComponent({ text }) {
  return <p>Текст: {text}</p>;
}

3. Ре-рендер родительского компонента

По умолчанию, если ререндерится родительский компонент, все его дочерние компоненты также ререндерятся (если не используются оптимизации).

function Parent() {
  const [state, setState] = useState(0);
  // При ререндере Parent, Child1 и Child2 также ререндерятся
  return (
    <div>
      <Child1 />
      <Child2 />
    </div>
  );
}

4. Изменение контекста (Context Change)

Когда компонент подписан на контекст через useContext или Context.Consumer, и значение этого контекста изменяется, компонент ререндерится.

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext); // Компонент ререндерится при изменении контекста
  return <button className={theme}>Кнопка</button>;
}

5. Принудительный ререндер (Force Update)

В классовых компонентах можно вызвать this.forceUpdate(), в функциональных — использовать хук useReducer или изменить ключ (key) компонента.

Когда ререндер НЕ происходит

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

  • Пропсы и состояние не изменились: React выполняет поверхностное сравнение (shallow comparison) пропсов и состояния.
  • Использование React.memo: Мемоизирует компонент, предотвращая ререндер, если пропсы не изменились.
  • shouldComponentUpdate (классовые компоненты): Позволяет вручную контролировать необходимость ререндера.
  • useMemo и useCallback: Мемоизируют значения и функции, предотвращая создание новых ссылок, которые могут вызвать ререндер дочерних компонентов.

Пример оптимизации с React.memo

const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
  // Тяжёлые вычисления
  const result = expensiveCalculation(data);
  return <div>{result}</div>;
});

function expensiveCalculation(data) {
  // Имитация сложных вычислений
  return data * 2;
}

function Parent() {
  const [count, setCount] = useState(0);
  const [data, setData] = useState(1);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Ререндер родителя: {count}</button>
      {/* ExpensiveComponent ререндерится ТОЛЬКО при изменении data, а не при каждом клике */}
      <ExpensiveComponent data={data} />
    </div>
  );
}

Важные нюансы

  1. Асинхронность: Ререндеры асинхронны и могут быть объединены (batched) React для производительности.
  2. Ссылочная целостность: При изменении объекта или массива в состоянии необходимо создавать новые ссылки, иначе React может не обнаружить изменение.
  3. Эффекты: useEffect с зависимостями запускается после рендера, если изменились указанные зависимости.

Вывод: Понимание триггеров ререндера критически важно для написания производительных React-приложений. Необходимо сочетать знание встроенных механизмов React (как React.memo, useMemo) с архитектурными решениями, чтобы минимизировать лишние ререндеры, но при этом не усложнять код преждевременными оптимизациями.