Почему React-компонент может вызываться два раза подряд?
Что проверяют
Знаете ли вы про StrictMode и умеете ли отличать поведение режима разработки от бага. Это вопрос на аккуратность: кандидат, который лечит двойной вызов удалением StrictMode, обычно пишет эффекты с побочными действиями и без очистки.
Как отвечать
Сначала уточните, что значит «вызывается»: функция компонента исполнилась дважды или дважды поменялся DOM. Дальше по причинам.
Самая частая: StrictMode в сборке для разработки намеренно вызывает функцию компонента дважды, а при монтировании прогоняет цикл монтирование, размонтирование, монтирование заново, поэтому эффект успевает отработать два раза. В продакшен-сборке этого нет. Смысл в проверке: рендер обязан быть чистым, а у каждого эффекта должна быть функция очистки.
Остальные причины настоящие:
- эффект на монтировании кладёт состояние, и рендер идёт второй раз;
- поменялся контекст или родитель отдал новое значение пропса;
setStateвызван прямо во время рендера, React перезапускает рендер;- поменялся
key, и компонент смонтировался заново.
Полезно добавить, что React пакетирует обновления состояния, поэтому два вызова setState подряд дают один рендер, а не два.
Где спотыкаются
Убирают StrictMode вместо того, чтобы починить эффект. Двойной вызов не причина проблемы, а её детектор: если от него ломается подписка, таймер или запрос, значит очистки нет, и в бою это утечёт по-другому.
Второе: считают рендеры счётчиком в useRef и делают выводы о производительности. В разработке число удвоено, замерять надо на продакшен-сборке или во вкладке Profiler.
Третье: видят два сетевых запроса при монтировании и объявляют это багом React. Запрос в эффекте без отмены через AbortController и без дедупликации на уровне клиента данных даст гонку и в проде, просто реже.