Каждый незавершённый заказ — потерянные деньги. Стандартный bitrix:sale.order.ajax на jQuery медленно отрисовывает блоки: обновление поля занимает 1–2 секунды, а при 10 000+ товарах — до 3 секунд. Пользователь уходит, конверсия падает. Настроить многошаговую форму, B2B-реквизиты или выбор даты доставки на этом компоненте практически невозможно — код превращается в лапшу из PHP-вставок и JavaScript.
Мы заменяем sale.order.ajax на React-чекаут под ключ. Наши инженеры — сертифицированные разработчики Битрикс с 10+ годами опыта. После внедрения у одного из клиентов конверсия выросла с 62% до 79% за 6 недель. Средний бюджет проекта — 150 000–400 000 ₽, окупаемость наступает через 4–5 месяцев. Если вы хотите таких же результатов, свяжитесь с нами — оценим ваш проект.
Почему React-чекаут быстрее и гибче стандартного компонента?
React-чекаут решает проблему на уровне архитектуры: UI в компонентах, логика в хуках, общение с сервером через API. Смена доставки обрабатывается за 200 мс, штатный компонент тратит больше секунды. Валидация полей выполняется мгновенно при потере фокуса — пользователь сразу видит ошибку, а не после нажатия кнопки.
Как устроена архитектура React-чекаута?
Оформление заказа делится на два независимых уровня: UI-уровень (React) и бизнес-логика (Битрикс на сервере). На фронте — React-приложение, которое управляет формой, показывает/скрывает шаги, рассчитывает итог в реальном времени. На сервере — Битрикс обрабатывает заказ через \Bitrix\Sale\Order, применяет скидки, рассчитывает стоимость доставки, проверяет остатки. Подробнее о системе заказов — в документации Bitrix Sale.
Ключевой API-метод для расчёта заказа без его создания:
// Расчёт итогов без сохранения заказа
$order = \Bitrix\Sale\Order::create(SITE_ID, $userId);
$basket = \Bitrix\Sale\Basket::loadSiteBasket(SITE_ID);
$order->setBasket($basket);
// Применяем параметры доставки
$shipment = $order->getShipmentCollection()->createItem(
\Bitrix\Sale\Delivery\Services\Manager::getById($deliveryId)
);
$shipment->setFields(['DELIVERY_ID' => $deliveryId, 'CURRENCY' => 'RUB']);
$shipment->calculateDelivery();
// Применяем купон
$order->getDiscountSystem()->calculate();
// Возвращаем итог без сохранения (без вызова $order->save())
return [
'subtotal' => $basket->getPrice(),
'delivery_price' => $shipment->getPrice(),
'discount' => $order->getDiscountPrice(),
'total' => $order->getPrice(),
];
Этот endpoint вызывается при каждом изменении полей: выбор службы доставки, ввод промокода, изменение количества. React получает актуальные цифры без перезагрузки.
Как интегрировать React-чекаут с Битрикс?
Для сложного чекаута (3+ шагов с валидацией) оптимальна библиотека React Hook Form с Zod-схемами валидации:
const checkoutSchema = z.object({
contact: z.object({
name: z.string().min(2, 'Укажите имя'),
phone: z.string().regex(/^\+7\d{10}$/, 'Неверный формат'),
email: z.string().email('Неверный email'),
}),
delivery: z.object({
type: z.enum(['courier', 'pickup', 'cdek']),
address: z.string().optional(),
pickupId: z.number().optional(),
}),
payment: z.object({
method: z.enum(['online', 'cash', 'invoice']),
}),
});
Стейт чекаута хранится в Zustand: шаги, текущий шаг, данные каждого шага, результат расчёта. При переходе между шагами данные не теряются, пользователь может вернуться назад.
Мы используем React Hook Form для валидации, Zustand для состояния и React Query для запросов.
| Технология |
Применение |
| React Hook Form + Zod |
Валидация форм с минимальным ререндером |
| Zustand |
Лёгкий state-менеджер для шагов и UI-состояний |
| React Query |
Кеширование запросов к API Битрикс, автоматический retry при сбоях |
Интеграция с картами для курьерской доставки
Яндекс.Карты или DaData для автодополнения адреса — стандартная задача для React-чекаута.
// Хук для автодополнения адреса через DaData
function useAddressSuggest(query: string) {
return useQuery({
queryKey: ['address-suggest', query],
queryFn: () => fetchDaDataSuggestions(query),
enabled: query.length > 3,
staleTime: 60_000,
});
}
При выборе адреса через DaData структурированные данные (город, улица, индекс) передаются в Битрикс отдельными полями — это упрощает последующую обработку заказа и передачу в службы доставки.
Кейс: чекаут для мебельного ритейлера
Наш клиент — интернет-магазин мебели с 2000+ SKU. Специфика: товары с разными сроками изготовления (от 3 до 40 дней), возможность заказать доставку на конкретную дату, обязательный замер для ряда товаров, B2B-оформление с реквизитами. Штатный sale.order.ajax не поддерживал ни выбор даты доставки, ни условное отображение блока замера, ни реквизиты компании в одном потоке.
Реализация:
-
Шаг 1 — контакты. Форма с телефоном и именем. Телефон валидируется через libphonenumber-js, подсказка через СМС-верификацию (опционально).
-
Шаг 2 — доставка. Динамическое отображение: если в заказе есть товары с замером — появляется блок «Запись на замер» с datepicker. Доступные даты загружаются с сервера (из CRM Битрикс, занятые слоты закрыты). Выбор даты доставки с учётом срока изготовления — минимальная дата рассчитывается на сервере по max(PRODUCTION_DAYS) в корзине.
-
Шаг 3 — оплата. Переключатель «Физическое лицо / Юридическое лицо». При выборе юрлица разворачивается блок реквизитов (ИНН → автозаполнение через DaData → подтягивание КПП, названия, адреса). Безналичный счёт для B2B генерируется автоматически после создания заказа через \Bitrix\Sale\PaySystem\Manager.
-
Создание заказа. Финальный POST отправляет все данные на сервер. Bitrix создаёт заказ, привязывает кастомные свойства (дата доставки, тип клиента, реквизиты), отправляет уведомления. React получает ID заказа и переводит пользователя на страницу «Спасибо».
| Шаг |
Штатный Битрикс |
React-чекаут |
| Выбор даты доставки |
Невозможно |
Datepicker с занятыми слотами |
| B2B-реквизиты |
Отдельная форма |
Inline, в том же потоке |
| Валидация в реальном времени |
Только при сабмите |
Мгновенно, по blur |
| Расчёт итогов при смене доставки |
Перезагрузка блока (>1 с) |
Без перезагрузки (<200 мс) |
Конверсия чекаута выросла с 62% до 79% за первые 6 недель после запуска.
Создание заказа на сервере
public function createOrderAction(array $data): array
{
$order = \Bitrix\Sale\Order::create(SITE_ID, $this->getCurrentUserId());
$basket = \Bitrix\Sale\Basket::loadSiteBasket(SITE_ID);
$order->setBasket($basket);
// Контакт
$order->setField('USER_DESCRIPTION', $data['comment'] ?? '');
// Доставка
$shipmentCollection = $order->getShipmentCollection();
$shipment = $shipmentCollection->createItem(
\Bitrix\Sale\Delivery\Services\Manager::getById($data['delivery_id'])
);
$shipment->setField('DELIVERY_ID', $data['delivery_id']);
// Оплата
$paymentCollection = $order->getPaymentCollection();
$payment = $paymentCollection->createItem(
\Bitrix\Sale\PaySystem\Manager::getObjectById($data['payment_id'])
);
$payment->setField('PAY_SYSTEM_ID', $data['payment_id']);
$payment->setField('SUM', $order->getPrice());
// Свойства заказа (адрес, телефон, ИНН и т.д.)
$propertyCollection = $order->getPropertyCollection();
foreach ($data['properties'] as $code => $value) {
$prop = $propertyCollection->getItemByOrderPropertyCode($code);
if ($prop) {
$prop->setValue($value);
}
}
$result = $order->save();
if (!$result->isSuccess()) {
throw new \Exception(implode(', ', $result->getErrorMessages()));
}
return ['order_id' => $order->getId()];
}
Обработка ошибок и edge cases
Недостаточный остаток товара при оформлении — обрабатывается на финальном шаге сохранения. React показывает модальное окно с перечнем недоступных позиций, предлагает удалить их или сохранить заказ без них.
Потеря соединения во время оформления — React Query с retry: 3 и уведомлением пользователю. Данные формы сохраняются в sessionStorage и восстанавливаются при перезагрузке.
Что входит в работу
- Проектирование шагов чекаута, условной логики, валидации
- Разработка API-контроллеров: расчёт заказа, создание, получение служб доставки и ПВЗ
- Создание React-приложения: форма, стейт-менеджер, интеграция с картами/DaData
- Привязка кастомных свойств заказа, настройка платёжных систем
- Тестирование edge cases: пустая корзина, нехватка остатка, таймаут сессии
- Документация по API и коду, обучение вашей команды
Готовы ускорить ваш чекаут? Закажите разработку React-чекаута — напишите нам. Получите консультацию по вашему проекту — мы расскажем, какие шаги нужны именно вам.
Что даёт React разработка для 1С-Битрикс и когда она нужна
Каталог на 30 000 SKU с фасетным фильтром — стандартный шаблон Битрикса грузит страницу за 3 секунды. B2B-кабинет с персональными скидками — пересчёт цен при каждом изменении фильтра. Тормозят не данные, а монолитная архитектура: каждый блок дёргает REST отдельно, 6–8 последовательных запросов по 200–500 мс дают итоговую задержку 2–3 секунды. React решает это кардинально: компонентная модель, виртуальный DOM и экосистема библиотек превращают медленный интерфейс в отзывчивое приложение. Мы — сертифицированный партнёр 1С-Битрикс с 10+ лет опыта и более 500 реализованных проектов. Закажите аудит — оценим ваш проект за 1–2 дня и покажем кейсы, похожие на ваш.
Архитектурные подходы
SPA на React + REST API Битрикс (BX.rest)
React-приложение живёт отдельно, стучится в /rest/ или кастомные эндпоинты через CRestServer. Максимум контроля, но и максимум работы.
- Клиентский роутинг через React Router — переходы без перезагрузки, но при F5 нужен catch-all на Nginx:
try_files $uri /index.html
- Оптимистичные обновления: корзина обновляется мгновенно,
sale.basket.update летит фоном. При ошибке откатываем стейт и показываем тост
- Фронтенд деплоится на CDN независимо от Битрикса — обновили кнопку, не трогая бэкенд
SSR с гидратацией — когда Яндекс не видит SPA
Яндекс научился рендерить JS, но неидеально; Googlebot лучше, но всё равно не 100%. Серверный рендеринг React-компонентов через Node.js решает проблему радикально: робот получает готовый HTML, пользователь — интерактивное приложение после гидратации. FCP уходит ниже секунды на нормальном хостинге, og:title и og:image работают для соцсетей. Сложность — нужен Node.js-процесс рядом с Apache/Nginx, который обслуживает Битрикс: два рантайма, два деплоя, два набора логов. Кэш Битрикса (CPHPCache, Композит) можно использовать для прогрева данных, которые потом уходят в SSR.
Headless Битрикс — админка для контент-менеджеров, React для посетителей
Контент-менеджер заходит в /bitrix/admin/, редактирует инфоблоки. Посетитель видит React-приложение, которое ходит за данными через API. Один бэкенд обслуживает сайт, мобильное приложение и Telegram-бота. Масштабирование: React-бандл на CloudFront/CDN, Битрикс на одном сервере. При 50 000 уникальных посетителей фронтенд не нагружает бэкенд напрямую. Ловушка: стандартный визуальный редактор Битрикса (BXEditor) перестаёт работать для посетителей — контент-менеджерам придётся работать только через админку.
Стек и компонентная архитектура
Стек, который реально используем
| Технология |
Зачем именно |
| React 18+ |
Suspense, useTransition — UI не блокируется при тяжёлых обновлениях каталога |
| TypeScript |
Типизация ответов API Битрикса — IBlockElement, BasketItem, Order. Без этого рефакторинг — русская рулетка |
| Vite |
HMR за 50 мс против 3–5 с у webpack. На проекте с 200 компонентами разница колоссальная |
| React Query |
useQuery(['catalog', sectionId]) — автоматический кэш, ревалидация, retry при 503 от перегруженного Битрикса |
| React Hook Form + Zod |
Оформление заказа: 15–20 полей, условная валидация (юрлицо — одни поля, физлицо — другие). RHF не ререндерит форму при каждом нажатии клавиши |
| Tailwind CSS |
Утилитарные классы — не боремся с каскадом из template_styles.css Битрикса |
| Radix UI / Shadcn |
Доступные примитивы с ARIA из коробки |
Как собираем компоненты и типизируем данные
Каждый проект начинается с дизайн-системы — иначе к третьему месяцу три разработчика напишут три разных компонента кнопки. Типографика, цвета, отступы — через CSS-переменные и Tailwind-конфиг. Формы: инпуты с масками (телефон, ИНН), селекты с поиском, загрузка файлов с превью и валидацией MIME. Карточка товара — отдельная история: цена с учётом скидок из CCatalogProduct::GetOptimalPrice(), лейблы «Хит»/«Новинка» из свойств инфоблока, кнопка «В корзину» с состояниями loading/success/error. Таблицы с виртуализацией (react-window) для прайсов на 5000+ строк.
Типизируем всё, что приходит из Битрикса. REST API возвращает string там, где ожидаешь number, "Y"/"N" вместо boolean, и null вместо пустого массива. Zod-схема на входе парсит и трансформирует — компоненты получают нормальные типы.
// Реальный тип ответа CIBlockElement через REST — сюрпризы повсюду
interface BitrixProduct {
ID: string; // да, string, не number
ACTIVE: "Y" | "N"; // не boolean
PRICE: string; // тоже string
QUANTITY: string; // и это string
}
Производительность и интеграция с API
Агрегирующие эндпоинты — база. Один ajax.php или кастомный контроллер на \Bitrix\Main\Engine\Controller собирает данные каталога, фильтров, корзины и пользователя за один запрос. React Query кэширует ответ, и повторный заход отдаёт из кэша с staleTime — загрузка сокращается на 60% уже на второй загрузке.
Как React улучшает Core Web Vitals
-
LCP < 2,5 с — lazy loading изображений через
loading="lazy", критический CSS инлайном, прелоад LCP-картинки через <link rel="preload">
-
INP (заменил FID) < 200 мс —
useTransition для тяжёлых фильтраций, useDeferredValue для поисковой строки
-
CLS < 0,1 — фиксированные размеры для скелетонов и изображений. Skeleton-плейсхолдеры вместо спиннеров
Виртуализация — не опция, а необходимость. Каталог с фасетным фильтром может вернуть 500 товаров на страницу. React-window или react-virtuoso рендерят только видимые 20–30 карточек — DOM не разбухает, скролл плавный.
REST и кастомные контроллеры
Из коробки через /rest/ доступны: инфоблоки (iblock.element.get), корзина (sale.basket.*), заказы (sale.order.*), пользователи (user.*). Для простого каталога достаточно. Но 70% задач требуют кастомных эндпоинтов. \Bitrix\Main\Engine\Controller — стандартный способ создавать свои эндпоинты в D7. Пишем контроллер, регистрируем через registerAction, получаем эндпоинт с CSRF-защитой и авторизацией из коробки.
- Агрегация: один запрос = данные каталога + фильтры + корзина + юзер
- WebSocket через Битрикс Push & Pull (
CPullStack::AddByTag) — статус заказа обновляется в реальном времени, без поллинга
- GraphQL-прослойка (webonyx/graphql-php) поверх D7 ORM — фронтенд запрашивает ровно те поля, которые нужны. Экономия трафика на мобильных до 40%
Проекты, сроки и что входит в работу
Типичные проекты, которые мы уже сделали
- Интернет-магазин на 30 000 SKU с фасетным фильтром через
\Bitrix\Iblock\PropertyIndex\Facet — SPA, React Query, виртуализация каталога
- B2B-кабинет: персональные цены из
CCatalogGroup, акты сверки из 1С через \Bitrix\Sale\Compatible\OrderCompatibility, история заказов с фильтрацией
- Корпоративный портал: дашборды на Recharts, real-time через Push & Pull, интеграция с внутренними API через middleware
- Маркетплейс: два React-приложения (покупатель + продавец), общий бэкенд, разделение данных через
CUser::GetUserGroup()
Сроки и что входит в работу
| Тип проекта |
Срок |
| Лендинг на React + Битрикс |
2–4 недели |
| Интернет-магазин SPA |
8–16 недель |
| Корпоративный портал |
10–20 недель |
| Миграция фронтенда на React (поэтапно) |
6–12 недель |
- Аудит текущего кода Битрикса и архитектуры
- Проектирование API-слоя (REST / кастомные контроллеры / GraphQL)
- Разработка дизайн-системы и компонентов
- Настройка CI/CD (деплой React-бандла независимо от Битрикса)
- Документация по эндпоинтам и типам (Swagger / TypeScript-типы)
- Передача доступов к серверу, админке, репозиторию
- Обучение контент-менеджеров работе через админку
- Гарантийная поддержка 2 месяца после сдачи
Точные цифры — после разбора ТЗ. Оценка поэтапная, с фиксированным бюджетом на каждый спринт.
Как мы внедряем React на проекте
- Аудит существующего кода — находим узкие места: избыточные запросы, устаревшие шаблоны, неоптимальные кэши.
- Проектирование слоя API — определяем, какие эндпоинты нужны, проектируем агрегаторы или GraphQL.
- Разработка дизайн-системы — создаём компоненты (кнопки, формы, карточки) на основе макетов или рекомендаций UX.
- Интеграция с Битриксом через выбранный подход (SPA, SSR или Headless) — настраиваем рендеринг и маршрутизацию.
- Тестирование и деплой — запускаем пилотный раздел (например, каталог), измеряем Core Web Vitals, после утверждения расширяем.
Типичные ошибки при внедрении React в Битрикс
- Игнорирование кэширования Битрикса — React Query может конфликтовать с композитным кэшем, если не настроить тегированное кэширование.
- Отсутствие обработки ошибок от REST — при 500-й ошибке интерфейс может «зависнуть». Нужен глобальный обработчик с fallback UI.
- Слишком много микро-компонентов — каждый маленький виджет дёргает API. Лучше агрегировать данные в одном запросе.
- Неверный порядок гидратации при SSR — данные с сервера должны точно совпадать с начальным стейтом клиента, иначе ошибки React hydration.
Почему React, а не Vue или шаблоны Битрикса
- Экосистема. Для любой UI-задачи есть готовая библиотека: таблицы, графики, drag-and-drop, виртуализация. Для Vue выбор уже, для шаблонов Битрикса — почти отсутствует.
- Кадры. React-разработчика найти в три раза проще, чем Битрикс-шаблонщика, знающего D7 и
template.php.
- React Native. Компоненты переиспользуются в мобильном приложении — не один-в-один, но бизнес-логика и типы шарятся.
- Поэтапное внедрение. Можно начать с одного раздела (
/catalog/) на React, остальное оставить на шаблонах Битрикса. component_epilog.php подключает React-бандл, данные прокидываются через window.__INITIAL_DATA__.
1С-Битрикс + React — это не теоретическая архитектура, а рабочая связка, которая уже обслуживает каталоги с десятками тысяч SKU и B2B-кабинеты с тяжёлой бизнес-логикой. Подробнее о React и 1С-Битрикс. Получите консультацию — пришлём вам кейсы, похожие на ваш проект. Свяжитесь с нами, чтобы обсудить детали. Реализуем под ключ с гарантией результата.