Код-ревью React-проекта перед приёмкой - это не пробежка глазами по diff в GitHub, а системная проверка архитектуры, состояния, производительности и безопасности кода. За несколько лет я принимал десятки CRM-панелей и SPA-сервисов на React, сделанных фрилансерами и аутсорс-командами, и почти всегда проблемы находятся не в синтаксисе, а в том, как разработчик обращается с состоянием и побочными эффектами. Ниже - чек-лист, по которому я сам прохожу код перед тем, как подписать акт приёмки или дать зелёный свет на мердж в прод.
Структура компонентов и архитектура React-проекта
Первое, на что смотрю, открыв репозиторий, - как разложены папки. Если в components лежит 120 файлов без деления на фичи или домены, это уже красный флаг: такой проект будет тяжело поддерживать через полгода, даже если сейчас всё работает. На CRM-панели для одного клиента я принимал именно такую структуру - все компоненты в одной плоской папке, включая формы заказов, виджеты аналитики и модалки настроек. Рефакторинг под feature-based структуру занял отдельные три дня работы, которые в бюджет проекта изначально не закладывались.
Смотрю на размер компонентов: если файл разросся за 300 строк и в нём смешаны разметка, бизнес-логика и запросы к API - это повод разбить его на кастомные хуки и презентационные компоненты. Отдельно проверяю, нет ли props drilling через четыре-пять уровней вложенности вместо Context или стейт-менеджера. Если пропсы прокидываются через компоненты, которые сами их не используют, а просто передают дальше, - это архитектурный долг, который со временем множит баги при рефакторинге.
Состояние, хуки и побочные эффекты в React-коде
Bольшинство реальных багов в React-проектах живёт в useEffect. Проверяю каждый эффект на три вещи: правильный массив зависимостей, cleanup-функцию там, где она нужна, и оправданность самого использования эффекта - часто разработчики тянут через useEffect то, что можно посчитать прямо при рендере через useMemo.
Пример из практики: в проекте с интеграцией через n8n данные заказов подтягивались в useEffect без AbortController и без очистки при размонтировании компонента. При быстром переключении фильтров это давало гонку запросов - интерфейс иногда показывал данные от предыдущего фильтра поверх актуальных. Рабочий вариант выглядит так:
useEffect(() => {
const controller = new AbortController();
fetchOrders(filterId, controller.signal)
.then(setOrders)
.catch((err) => {
if (err.name !== 'AbortError') setError(err);
});
return () => controller.abort();
}, [filterId]);
Отдельно смотрю на выбор стейт-менеджера и на то, насколько он соответствует размеру проекта. Redux Toolkit на лендинге с тремя формами - это оверинжиниринг, который увеличивает время на онбординг нового разработчика. А голый useState с прокидыванием через семь компонентов на панели с 40 экранами - обратная крайность. Zustand или Context с useReducer чаще всего оказываются золотой серединой для проектов среднего размера.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Производительность: ре-рендеры, мемоизация и размер бандла
Проверяю производительность не через ощущения, а через React DevTools Profiler: смотрю, какие компоненты перерендериваются при простых действиях вроде ввода текста в поле поиска. Если весь список из 200 карточек товаров перерисовывается при каждом нажатии клавиши, потому что состояние поиска лежит в общем родителе без мемоизации дочерних элементов, - это конкретная и легко чинимая проблема.
На что смотрю по производительности:
- React.memo на компонентах списков и карточек, которые рендерятся десятками
- useMemo и useCallback не расставлены бездумно везде, а применяются там, где реально есть дорогие вычисления или стабильность ссылок важна для дочерних мемо-компонентов
- Виртуализация длинных списков (react-window или аналог) для таблиц от нескольких сотен строк - актуально для дашбордов и админок
- Код-сплиттинг через lazy и Suspense для маршрутов, которые не нужны на первом экране
- Размер итогового бандла - прогоняю через source-map-explorer, чтобы найти случайно затянутые целиком библиотеки вроде lodash или moment
На одном из дашбордов с BI-виджетами на Vue.js в соседнем проекте разница между до и после виртуализации таблицы на 5000 строк была в буквальном смысле секунды загрузки против почти мгновенного рендера - тот же принцип применим и к React-таблицам без исключений.
Безопасность React-кода: XSS, секреты и запросы к API
Безопасность в код-ревью React-проекта проверяю по трём направлениям. Первое - использование dangerouslySetInnerHTML: если контент из CMS или пользовательского ввода вставляется без санитайзера вроде DOMPurify, это прямая дыра под XSS. Второе - секреты в коде: API-ключи для эквайринга или сторонних сервисов не должны попадать в клиентский бандл, только в переменные окружения на бэкенде или в серверные роуты. Видел случай, когда ключ от T‑Bank эквайринга оказался прямо в собранном JS-файле фронтенда - его можно было достать через обычный просмотр исходного кода в браузере.
Третье - обработка ответов от внешних API и виджетов. Если в форме заказа стоит интеграция с СДЭК для расчёта доставки, проверяю, что фронтенд не доверяет слепо ответу виджета и что расчёт стоимости валидируется на сервере перед оплатой - иначе через devtools можно подменить сумму заказа прямо в запросе. Отдельно смотрю на CORS-настройки и на то, не остались ли в проде дебажные эндпоинты или моковые данные, которые должны были уйти вместе с разработческим окружением.
Тесты и типизация - минимальный порог для приёмки
Не требую 100% покрытия тестами - это редко оправдано по срокам и бюджету. Но смотрю на то, покрыты ли тестами бизнес-критичные сценарии: оформление заказа, авторизация, расчёт суммы, отправка формы. Для React Testing Library проверяю, что тесты проверяют поведение через доступный интерфейс (getByRole, getByText), а не завязаны на детали реализации вроде классов или структуры DOM - иначе тесты будут ломаться при каждом косметическом рефакторинге и превратятся в обузу, а не в страховку.
По TypeScript смотрю на strict-режим в tsconfig и на количество any в кодовой базе - команда grep ‑r “any” src - include=*.tsx даёт быструю оценку. Десяток any в утилитах - нормально, полсотни any в бизнес-логике форм и запросов - сигнал, что типизация добавлена для галочки, а не для реальной защиты от ошибок. Также проверяю, что типы пропсов компонентов не дублируют интерфейсы API вручную, а генерируются или переиспользуются из единого источника, иначе типы и бэкенд быстро разъезжаются.
Чек-лист ревьюера: таблица по областям проверки
Собрал в таблицу то, с чего начинаю проверку каждого React-проекта перед приёмкой - удобно держать под рукой при первом проходе по репозиторию.
| Область | На что смотреть | Красный флаг |
|---|---|---|
| Структура | Деление по фичам, размер компонентов | Плоская папка components на 100+ файлов |
| Состояние | Зависимости useEffect, cleanup-функции | Пустой массив зависимостей при реальных внешних значениях |
| Производительность | Профилировщик, размер бандла | Ре-рендер всего списка при вводе текста |
| Безопасность | dangerouslySetInnerHTML, переменные окружения | API-ключи в клиентском бандле |
| Тесты | Покрытие критичных сценариев | Тесты завязаны на CSS-классы вместо ролей |
| Типизация | strict-режим, количество any | any в основных бизнес-компонентах |
Если по итогам ревью выясняется, что стейт-менеджмент и структура компонентов проще переписать заново, чем чинить точечно, - на этом же этапе стоит прикинуть, что дешевле: доработка текущей кодовой базы или заказ CRM-панели на React с нуля. Иногда правки растягиваются на недели и по итоговой стоимости обгоняют разработку с чистого листа.
Разобраться перед стартом
Консультация
от 3 000 ₽
Подробнее →Частые вопросы
Сколько времени занимает полное код-ревью React-проекта среднего размера
Для панели на 40-60 компонентов с базовой бизнес-логикой закладываю от 4 до 8 часов на первый проход: структура, хуки, производительность, безопасность. Если находятся системные проблемы вроде отсутствия типизации или тестов на критичных сценариях, повторный детальный разбор конкретных модулей добавляет ещё несколько часов.
Нужно ли требовать 100% покрытие тестами перед приёмкой
Нет, для большинства коммерческих проектов это избыточно и не окупается по срокам. Важнее покрыть бизнес-критичные сценарии - оплату, авторизацию, отправку форм - чем гнаться за процентом покрытия ради цифры в отчёте.
Что делать, если ревью выявило серьёзные архитектурные проблемы уже после приёмки
Фиксирую конкретные находки с примерами кода и оцениваю трудозатраты на исправление отдельно от исходного техзадания - это отдельная работа, которую нужно обсуждать как доработку, а не как гарантийный случай, если проблема не была прописана в критериях приёмки изначально.
Можно ли провести код-ревью без доступа к репозиторию, только по демо-версии
Частично - по демо оцениваются производительность и заметные баги в поведении интерфейса, но структуру компонентов, состояние и безопасность кода без доступа к исходникам проверить нельзя. Для полноценного ревью нужен хотя бы read-only доступ к репозиторию.