> Почему React-компонент может вызываться два раза подряд? (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: КИТМЕД

Стек: React

> Пример ответа

Короткий ответ

Двойной вызов React-компонента - это ожидаемое поведение в React 18+ в режиме strict mode. React намеренно вызывает функцию компонента дважды в development-сборке, чтобы обнаружить побочные эффекты, которые могут привести к багам. В production-сборке компонент вызывается один раз.

Подробное объяснение

Начиная с React 18, в strict mode компоненты вызываются дважды в development-окружении. Это не баг, а фича для выявления проблем с чистотой рендеринга. React монтирует компонент, размонтирует его и монтирует снова, вызывая функцию компонента дважды подряд. Это помогает обнаружить:

  • Побочные эффекты в теле компонента (например, мутации внешних переменных)
  • Неправильное использование хуков (useEffect, useMemo, useCallback)
  • Проблемы с инициализацией состояния
  • Утечки памяти из-за неправильной очистки эффектов

React проверяет, что компонент ведёт себя как чистая функция: при одинаковых props и state возвращает одинаковый JSX. Если при повторном вызове результат отличается, это сигнал о проблеме.

На практике

Для senior-разработчика важно понимать, что двойной вызов - это инструмент отладки, а не runtime-баг. При работе с:

  • useEffect: проверяется, что cleanup-функция корректно отрабатывает
  • useMemo/useCallback: проверяется, что вычисления не имеют побочных эффектов
  • инициализация состояния: проверяется, что начальное состояние не зависит от внешних мутаций

В production-сборке (NODE_ENV=production) двойного вызова не происходит. Если вы видите двойной вызов в production - это отдельная проблема, связанная с архитектурой приложения (например, лишние ререндеры из-за неправильных зависимостей).

Пример кода

JSX
function Counter() {
console.log('Component called'); // будет дважды в development strict mode
const [count, setCount] = useState(() => {
console.log('Initializer called'); // тоже дважды
return 0;
});
useEffect(() => {
console.log('Effect runs'); // один раз
return () => console.log('Cleanup'); // один раз
}, []);
return <div>{count}</div>;
}

Как отвечать на собеседовании

Начни с того, что это intentional behavior в React 18+ strict mode для development. Объясни, что React проверяет чистоту компонента. Упомяни, что в production этого нет. Покажи понимание, как это влияет на useEffect, useMemo и инициализацию state. Добавь, что это помогает ловить баги на раннем этапе, особенно с асинхронными операциями и подписками.

Что проверяет интервьюер

  • Понимание разницы между development и production сборками
  • Знание strict mode и его целей
  • Умение отличать intentional behavior от багов
  • Понимание концепции чистых компонентов
  • Опыт работы с побочными эффектами в React

Типичные ошибки

  • Считать двойной вызов багом React
  • Пытаться "исправить" это через обёртки или мемоизацию
  • Не знать, что в production этого не происходит
  • Путать двойной вызов компонента с двойным вызовом эффекта (useEffect выполняется один раз)
  • Думать, что это связано с Concurrent Mode или Suspense

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью