Не доверяйте React Compiler: реальный опыт внедрения и подводные камни ⚛️
Опыт внедрения React Compiler: React Hook Form, устаревшие коллбэки, значок Memo и безопасная миграция.

Помните громкие обещания о том, что с выходом стабильного React Compiler мы наконец-то сможем выпилить из кодовых баз тонны useMemo и useCallback, а компилятор сам всё идеально порежет на гранулярный кэш?
На бумаге звучит красиво, но в реальности автоматическая оптимизация — это палка о двух концах. Разработчик Исаак Окоро протестировал компилятор на живом продакшене под Next.js и выкатил детальный разбор того, что пошло не так. Спойлер: «почти всё заработало», но то, что сломалось, без хороших интеграционных тестов гарантированно улетело бы ранить пользователей.
Главные технические инсайды и грабли:
1. Зависание интерактивного превью (Боль с React Hook Form). В форме использовался стандартный watch('name'). Без компилятора всё обновлялось посимвольно. После включения — превью намертво «замёрзло», хотя валидация и отправка работали.
- В чём проблема: Архитектура React Hook Form и аналогичных завязана на глубокую мутацию объектов. Компилятор же свято верит, что ваш код абсолютно чистый (pure) и предсказуемый. Столкнувшись с такой мутацией, он просто ломает реактивность. Линтер сразу выдал ошибку, а лечить пришлось костылём в виде обёртки с директивой
"use no memo". 2. Проблема «протухания» данных. Автор с корнем вырезал ручнойuseCallbackиз обработчика кликов по графику, который инициализировался внутриuseEffect. Под нагрузкой клики начали ссылаться на устаревшие данные из прошлых рендеров. - В чём проблема: Это не баг компилятора, это тайминги самого
useEffect. Ручной хук жестко фиксировал ссылку и делал перерегистрацию эффекта предсказуемой. Автоматика с этим не справилась. Коллбэк пришлось вернуть руками. 3. Миф о шильдике «Memo ✨» в DevTools. Многие думали: если в React DevTools у компонента загорелась заветная иконка со звездочками, значит, он оптимизирован. Ничего подобного. Автор специально скормил компилятору компонент, где пропсы мутировали напрямую через.sort(). Линтер кричал об ошибке, код нарушал правила React, но значок «Memo» всё равно гордо красовался в DevTools. - Вывод: Иконка показывает лишь то, что компилятор обработал код на этапе сборки, но она не гарантирует, что оптимизация не сломала рантайм. Смотреть нужно строго в Profiler.
Что в итоге? Сносить useMemo и useCallback? Удалять можно и нужно, но точечно. Автоматический кэш действительно работает глубже и эффективнее ручного, но старые хуки нужно оставить, если:
- Вы работаете со сторонними non-React библиотеками (графики, холсты/Canvas, SDK), которые регистрируют коллбэки строго по ссылке.
- Вы вешаете кастомные слушатели напрямую на DOM API за пределами жизненного цикла React.
- У вас реально тяжелые вычисления на сотни миллисекунд (тут
useMemoнужен хотя бы как документ для коллег, объясняющий: «не трогай, тут дорого»).
Чек-лист для переезда: Сначала ставим свежий eslint-plugin-react-hooks и переводим правила unsupported-syntax и incompatible-library в статус error. Чистим кодовую базу от того, что подсветит линтер. И только потом включаем компилятор в экспериментах, обязательно зафиксировав версию плагина через --save-exact, чтобы минорный апдейт не перекосил логику сборки.
Как у вас дела с React Compiler? Пробовали затаскивать в крупные проекты или пока держитесь за ручные зависимости в хуках, потому что «оно надёжнее»? 👇