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

Когда выполнится useEffect, если массив зависимостей пуст - до или после рендера?

2.2 Middle🔥 221 комментариев
#React

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

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

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

Подробный разминк useEffect с пустым массивом зависимостей

useEffect с пустым массивом зависимостей ([]) выполняется после рендера компонента. Давайте разберем этот процесс детально, так как понимание жизненного цикла компонента критически важно для разработчика React.

Жизненный цикл компонента и порядок выполнения

Когда функциональный компонент с useEffect рендерится:

  1. Выполнение тела компонента — React вычисляет JSX, вызывая ваш функциональный компонент.
  2. Рендер в DOM — React применяет результат вычисления JSX к DOM (этап "commit phase").
  3. Выполнение useEffect после коммитаТолько после того как DOM обновлен, React запускает useEffect.

Ключевое отличие от componentDidMount

Многие разработчики проводят аналогию между useEffect с пустым массивом и методом componentDidMount в классовых компонентах, но есть важное различие:

// Функциональный компонент с useEffect
function MyComponent() {
  useEffect(() => {
    console.log('useEffect с [] выполняется ПОСЛЕ рендера');
    // Здесь можно безопасно работать с DOM-элементами
    const element = document.getElementById('myElement');
    if (element) {
      element.style.color = 'red';
    }
  }, []); // Пустой массив зависимостей

  console.log('Тело компонента выполняется ПЕРЕД useEffect');
  
  return (
    <div id="myElement">
      Содержимое компонента
    </div>
  );
}

В этом примере в консоли сначала появится "Тело компонента выполняется ПЕРЕД useEffect", и только потом — "useEffect с [] выполняется ПОСЛЕ рендера".

Почему так спроектировано?

Архитектурное решение React имеет глубокий смысл:

  • Предсказуемость: Гарантия, что при выполнении эффекта DOM уже обновлен
  • Безопасность операций с DOM: В эффекте можно безопасно обращаться к DOM-элементам
  • Избежание визуальных рывков: Эффекты, которые меняют внешний вид, выполняются после отрисовки

Практические сценарии использования

function DataFetcher() {
  const [data, setData] = useState(null);

  // Типичный случай: загрузка данных при монтировании
  useEffect(() => {
    console.log('Начинаю загрузку данных...');
    
    fetch('/api/data')
      .then(response => response.json())
      .then(data => {
        setData(data); // Установка данных вызовет повторный рендер
        console.log('Данные загружены и установлены');
      });
  }, []); // Пустой массив = выполнить только при монтировании

  return (
    <div>
      {data ? (
        <DataView data={data} />
      ) : (
        <LoadingIndicator />
      )}
    </div>
  );
}

Важные нюансы поведения

  • Строго после каждого рендера? Нет, только после первого рендера при монтировании компонента
  • Что насчёт cleanup-функции? Она выполнится при размонтировании компонента:
useEffect(() => {
  const timerId = setInterval(() => {
    console.log('Тик');
  }, 1000);
  
  // Функция очистки выполнится при размонтировании компонента
  return () => {
    console.log('Очистка эффекта');
    clearInterval(timerId);
  };
}, []); // Выполняется только при монтировании
  • Строгий режим React (Strict Mode) в development может вызывать двойное выполнение эффекта для обнаружения побочных эффектов

Сравнение с другими вариантами useEffect

useEffect(() => {
  // БЕЗ массива зависимостей: выполняется после КАЖДОГО рендера
});

useEffect(() => {
  // С пустым массивом []: выполняется только после ПЕРВОГО рендера
}, []);

useEffect(() => {
  // С зависимостями [dep1, dep2]: выполняется после рендера, 
  // если изменилась хотя бы одна зависимость
}, [dep1, dep2]);

Заключение

Таким образом, ответ на вопрос: useEffect всегда выполняется после рендера компонента, независимо от массива зависимостей. Пустой массив зависимостей лишь ограничивает выполнение эффекта только первым рендером (монтированием), но не меняет базового порядка: сначала выполняется тело компонента и рендер в DOM, затем — эффект.

Это фундаментальное понимание помогает избегать распространенных ошибок, когда разработчики пытаются в эффекте использовать значения, которые ещё не существуют в DOM, или неправильно рассчитывают на синхронность выполнения кода.