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

Что такое перерисовка в React?

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

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

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

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

Что такое перерисовка (Re-render) в React?

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

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

  1. Триггеры перерисовки:
    *   **Изменение состояния (`useState`, `setState`, `useReducer`)** — самый частый триггер. Вызов функции обновления состояния помечает компонент для повторного рендеринга.
    *   **Изменение пропсов** — когда родительский компонент передаёт новые пропсы (или изменённые ссылки на объекты/функции).
    *   **Изменение контекста (`useContext`)** — если подписанный на контекст компонент получает новое значение от провайдера.
    *   **Принудительная перерисовка** — вызов `forceUpdate()` в классовых компонентах (крайне не рекомендуется).

  1. Механизм работы:
    React не трогает реальный DOM сразу. Сначала на основе нового вызова компонента создаётся **новое дерево React-элементов (Virtual DOM)**. Затем React сравнивает его с предыдущим деревом с помощью **алгоритма согласования (Reconciliation)** и вычисляет **минимальный набор изменений (diff)**, которые нужно применить к реальному DOM. Только эти вычисленные изменения применяются, что делает обновления эффективными.

```jsx
// Пример: триггер перерисовки через изменение состояния
import { useState } from 'react';

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

  // При каждом клике setCount вызывает перерисовку компонента
  const handleClick = () => {
    setCount(count + 1); // Новое значение -> триггер перерисовки
  };

  // Эта функция выполняется при каждой перерисовке
  console.log('Компонент перерисован!');
  return (
    <div>
      <p>Счётчик: {count}</p>
      <button onClick={handleClick}>Увеличить</button>
    </div>
  );
}
```

3. Важные уточнения:

    *   **Родитель → дети**: Перерисовка родительского компонента **по умолчанию** вызывает перерисовку **всех его дочерних компонентов**, независимо от изменения их пропсов. Это может привести к проблемам производительности в больших деревьях.
    *   **Неравенство по ссылке**: React использует **поверхностное сравнение (shallow comparison)** для пропсов и состояния. Если передаётся новый объект или функция (даже с идентичным содержимым), React считает, что пропсы изменились.
    ```jsx
    // Этот компонент будет перерисовываться при каждом рендере родителя,
    // потому что массив items каждый раз создаётся заново (новая ссылка).
    function Parent() {
      const items = [1, 2, 3]; // Новая ссылка при каждом рендере!
      return <Child items={items} />;
    }
    ```

Управление перерисовками для оптимизации производительности:

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

  • React.memo(): Компонент высшего порядка для мемоизации. Запоминает результат рендера и пропускает перерисовку, если пропсы (по ссылкам) не изменились.
    const MyComponent = React.memo(function MyComponent(props) {
      // Рендер только если props изменились
      return <div>{props.value}</div>;
    });
    
  • useMemo(): Кэширует результат вычислений между рендерами. Пересчитывает значение только при изменении зависимостей.
    const expensiveValue = useMemo(() => {
      return computeExpensiveValue(a, b); // Выполняется только при изменении a или b
    }, [a, b]);
    
  • useCallback(): Кэширует саму функцию между рендерами, стабилизируя ссылку. Это предотвращает ненужные перерисовки дочерних компонентов, которые зависят от этой функции как пропса.
    const memoizedCallback = useCallback(() => {
      doSomething(a, b); // Функция сохраняет ссылку при неизменных зависимостях
    }, [a, b]);
    

Заключение

Перерисовка — это фундаментальный и ожидаемый механизм React, обеспечивающий реактивность интерфейса. Не нужно бояться всех перерисовок — React оптимизирует обновление реального DOM. Однако в глубоких или часто обновляемых компонентах избыточные перерисовки могут стать узким местом. Ключ к производительности — понимание, когда и почему происходят перерисовки, и грамотное применение оптимизаций (memo, useMemo, useCallback) там, где это действительно необходимо, а не повсеместно.

Что такое перерисовка в React? | PrepBro