Является ли рендеринг в React блокирующей операцией для исполнения JavaScript кода
Что проверяют
Понимаете ли вы, что React это обычный синхронный JavaScript в одном потоке, и не переносите ли слово «асинхронный» с планирования на само выполнение. Для серверной стороны вопрос острее: там рендер конкурирует не с анимацией, а с обработкой чужих запросов.
Как отвечать
Да, блокирует. Рендер это вызов функций компонентов и сверка деревьев, всё в том же потоке, где крутится остальной JavaScript. Пока идёт рендер, событийный цикл не обрабатывает ни таймеры, ни колбэки ввода-вывода.
Виртуальный DOM ничего не делает асинхронным, он лишь сокращает число операций с настоящим DOM. Фаза коммита синхронна и непрерываема всегда.
Что изменил конкурентный режим: рендер можно нарезать на части и отдавать управление между компонентами, если работа помечена как несрочная через startTransition или useDeferredValue. Поток по-прежнему один, суммарная работа та же, но ввод пользователя не ждёт конца длинного рендера. Это планирование, а не параллелизм.
На сервере в Node разница ещё заметнее:
// блокирует цикл событий до конца дерева
const html = renderToString(<App />);
// отдаёт куски и уступает циклу
const stream = renderToPipeableStream(<App />, { onShellReady });renderToString синхронен целиком, поэтому тяжёлая страница одного клиента задерживает ответы всем остальным на этом процессе. Потоковый рендер вместе с границами Suspense позволяет отдать оболочку рано и не держать цикл событий занятым единым куском.
Где спотыкаются
Называют рендер асинхронным на том основании, что React может отложить его запуск. Отложенный старт и неблокирующее выполнение это разные вещи: работа всё равно выполнится целиком на том же потоке.
Пытаются лечить долгий рендер обёрткой в промис или setTimeout. Задача просто переедет в другой тик, кадр всё равно будет пропущен. Помогает уменьшение объёма работы: виртуализация списка, вынос расчётов в useMemo или в отдельный воркер.
На сервере измеряют только среднее время ответа. Синхронный рендер бьёт по хвосту распределения: под нагрузкой встают запросы, которые сами по себе ничего тяжёлого не делают.