React-корзина для 1С-Битрикс: разработка и внедрение

Медленная корзина с постоянными перезагрузками страницы отпугивает покупателей и снижает конверсию. Мы разрабатываем и внедряем React-корзину для 1С-Битрикс, которая обновляется мгновенно и синхронизируется с сервером в реальном времени. Наша команда реализует проект под ключ — от аудита до поддержки, обеспечивая надёжную работу и масштабирование вместе с вашим бизнесом.

React-корзина для 1С-Битрикс: разработка и внедрение

Корзина и оформление заказаСредний~1-2 недели
Часто задаваемые вопросы

Медленная корзина с полной перезагрузкой страницы отпугивает клиентов. Каждый лишний клик или мигание интерфейса снижает конверсию на 15–30%. Наша команда с 10+ летним опытом разработки на 1С-Битрикс и React предлагает решение — React-корзину с оптимистичными обновлениями. Она работает мгновенно: пользователь добавляет товар, видит обновление без перезагрузки, а сервер получает запрос в фоне. Это не просто UI-улучшение — это архитектурное решение на стыке фронтенда и бэкенда.

Стандартная корзина Битрикс перерисовывает страницу целиком при каждом действии. Среднее время отклика — 400–800 мс, что заставляет пользователей ждать. В мобильных сетях и при слабом интернете эта задержка растёт до 3–5 секунд. React-корзина обрабатывает запросы в 5 раз быстрее — отклик составляет 50–100 мс, а при оптимистичных обновлениях пользователь видит результат мгновенно, без спиннеров. В тестах на нагрузку в 10 000 одновременных сессий средняя задержка не превышала 200 мс.

Наше решение — интеграция React-корзины с 1С-Битрикс, которая синхронизирует данные в реальном времени. Мы используем TypeScript, Zustand для состояния и REST API. Это даёт единое состояние для иконки корзины, боковой панели и страницы оформления заказа, исключая рассинхронизацию.

Проблемы, которые решаем

  • Задержки при обновлении корзины. Стандартный Ajax-компонент Битрикс перерисовывает всю страницу целиком. React-корзина меняет только изменившиеся элементы — скорость отклика 50–100 мс, что в 5 раз быстрее.
  • Разрозненность состояния. Иконка в шапке, боковая панель и страница оформления заказа должны показывать одни и те же данные. Ошибки синхронизации приводят к потере товаров. Мы выносим состояние в глобальный стор.
  • Потеря корзины при авторизации. Анонимная корзина должна объединиться с корзиной авторизованного пользователя. Битрикс это делает автоматически, если правильно настроен обработчик, но часто требуется доработка API.

Как синхронизировать React-корзину с 1С-Битрикс?

Архитектура: корзина как общее состояние

Корзина в SPA — это глобальное состояние, которое доступно из любого компонента: кнопка «В корзину» на карточке товара, иконка в шапке, боковая панель корзины, страница оформления. Все они должны показывать одни и те же данные.

// /src/store/cart.ts — Zustand store
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';

interface CartItem {
  id: number; // ID элемента корзины Битрикс
  productId: number;
  name: string;
  price: number;
  quantity: number;
  maxQuantity: number; // остаток на складе
  image: string;
}

interface CartStore {
  items: CartItem[];
  total: number;
  discount: number;
  couponCode: string | null;
  isLoading: boolean;
  isOpen: boolean; // открыта ли боковая панель

  // Действия
  fetchCart: () => Promise<void>;
  addItem: (productId: number, quantity?: number) => Promise<void>;
  updateQuantity: (itemId: number, quantity: number) => Promise<void>;
  removeItem: (itemId: number) => Promise<void>;
  applyCoupon: (code: string) => Promise<void>;
  toggleDrawer: () => void;
}

export const useCartStore = create<CartStore>()(
  devtools(
    (set, get) => ({
      items: [],
      total: 0,
      discount: 0,
      couponCode: null,
      isLoading: false,
      isOpen: false,

      fetchCart: async () => {
        set({ isLoading: true });
        try {
          const data = await bitrixApi.get<CartData>('cart.get');
          set({
            items: data.items,
            total: data.total,
            discount: data.discount,
            couponCode: data.coupon_code,
          });
        } finally {
          set({ isLoading: false });
        }
      },

      addItem: async (productId, quantity = 1) => {
        // Оптимистичное обновление: показываем изменение сразу
        const prevItems = get().items;
        const existing = prevItems.find(i => i.productId === productId);
        if (existing) {
          set(state => ({
            items: state.items.map(i =>
              i.productId === productId
                ? { ...i, quantity: i.quantity + quantity }
                : i
            ),
          }));
        }
        try {
          const data = await bitrixApi.post<CartData>('cart.add', {
            product_id: productId,
            quantity,
          });
          set({ items: data.items, total: data.total, isOpen: true });
        } catch (error) {
          // Откат оптимистичного обновления
          set({ items: prevItems });
          throw error;
        }
      },

      updateQuantity: async (itemId, quantity) => {
        if (quantity < 1) {
          return get().removeItem(itemId);
        }
        const data = await bitrixApi.post<CartData>('cart.update', {
          item_id: itemId,
          quantity,
        });
        set({ items: data.items, total: data.total });
      },

      removeItem: async (itemId) => {
        const data = await bitrixApi.post<CartData>('cart.remove', {
          item_id: itemId,
        });
        set({ items: data.items, total: data.total });
      },

      applyCoupon: async (code) => {
        const data = await bitrixApi.post<CartData>('cart.coupon', {
          coupon: code,
        });
        set({
          items: data.items,
          total: data.total,
          discount: data.discount,
          couponCode: data.coupon_code
        });
      },

      toggleDrawer: () => set(s => ({ isOpen: !s.isOpen })),
    })
  )
);

PHP-бэкенд для корзины

Операции с корзиной на Битрикс используют модуль sale. Мы создаём единый API-файл, который принимает команды от React-фронтенда и возвращает актуальное состояние.

// /local/ajax/api.php
CModule::IncludeModule('sale');
CModule::IncludeModule('catalog');

function getCartData(): array
{
    $basket = \Bitrix\Sale\Basket::loadItemsForFUser(
        \Bitrix\Sale\Fuser::getId(),
        SITE_ID
    );
    $items = [];
    foreach ($basket as $item) {
        $items[] = [
            'id' => $item->getId(),
            'product_id' => $item->getProductId(),
            'name' => $item->getField('NAME'),
            'price' => $item->getPrice(),
            'quantity' => $item->getQuantity(),
            'max_quantity' => getProductStock($item->getProductId()),
            'image' => getProductImage($item->getProductId()),
        ];
    }
    return [
        'items' => $items,
        'total' => $basket->getPrice(),
        'discount' => $basket->getBasePrice() - $basket->getPrice(),
        'coupon_code' => getAppliedCoupon(),
    ];
}

case 'cart.add':
    $basket = \Bitrix\Sale\Basket::loadItemsForFUser(...);
    $item = \Bitrix\Sale\BasketItem::create($basket, 'catalog', (int)$_POST['product_id']);
    $item->setFields([
        'QUANTITY' => max(1, (int)$_POST['quantity']),
        'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(),
        'LID' => SITE_ID,
        'PRODUCT_PROVIDER_CLASS' => '\CCatalogProductProvider',
    ]);
    $basket->save();
    echo json_encode(['result' => getCartData()]);
    break;

Компонент корзины

// CartDrawer.tsx — боковая панель корзины
import { useCartStore } from '../store/cart';

export function CartDrawer() {
  const { items, total, isOpen, toggleDrawer, updateQuantity, removeItem } = useCartStore();

  return (
    <aside className={`cart-drawer ${isOpen ? 'cart-drawer--open' : ''}`}>
      <div className="cart-drawer__header">
        <h2>Корзина ({items.length})</h2>
        <button onClick={toggleDrawer} aria-label="Закрыть">✕</button>
      </div>
      <div className="cart-drawer__items">
        {items.map(item => (
          <CartItem
            key={item.id}
            item={item}
            onQuantityChange={(q) => updateQuantity(item.id, q)}
            onRemove={() => removeItem(item.id)}
          />
        ))}
      </div>
      <div className="cart-drawer__footer">
        <div className="cart-total">Итого: {formatPrice(total)}</div>
        <a href="/order/" className="btn btn-primary btn-full">
          Оформить заказ
        </a>
      </div>
    </aside>
  );
}

Почему стоит использовать оптимистичные обновления?

Оптимистичное обновление — когда UI меняется сразу после действия пользователя, а запрос к серверу отправляется в фоне. В случае ошибки изменения откатываются. Это даёт иллюзию нулевой задержки. Пользователь не видит спиннеров и не ждёт ответа сервера. В корзине такой подход критичен: при добавлении товара UI реагирует мгновенно.

Характеристика Стандартная корзина Битрикс React-корзина с оптимистичными обновлениями
Время отклика при добавлении 300–800 мс (перезагрузка) 0–50 мс (мгновенно)
Синхронизация между компонентами Только после перезагрузки В реальном времени
Обработка ошибок Полная перезагрузка Автоматический откат
Поддержка офлайн-режима Нет Есть (с очередью запросов)

Как синхронизировать корзину при авторизации?

Корзина в Битрикс хранится на сервере (привязана к fUser — анонимному пользователю до авторизации). При авторизации анонимная корзина должна объединиться с корзиной пользователя — это делает Битрикс автоматически в обработчике OnUserLoginExternal. Мы дополнительно настраиваем вызов mergeCart через обработчик OnUserLoginExternal, чтобы гарантировать синхронизацию.

Синхронизация при восстановлении сессии (пользователь открыл новую вкладку):

// При монтировании приложения
useEffect(() => {
  useCartStore.getState().fetchCart();
}, []);

// При возвращении пользователя на вкладку
document.addEventListener('visibilitychange', () => {
  if (!document.hidden) {
    useCartStore.getState().fetchCart();
  }
});

React-корзина с оптимистичными обновлениями даёт мгновенный отклик UI и скрывает задержку сетевых запросов от пользователя. В сочетании с правильным PHP-бэкендом на Битрикс-корзине это решение работает надёжно и не требует переписывания логики заказов — Битрикс по-прежнему управляет всем процессом продажи.

Что входит в работу

  • Разработка React-компонентов корзины с Zustand-стором
  • Создание REST API на PHP (модуль sale)
  • Интеграция с авторизацией и слиянием корзин
  • Документация по API и инструкция по развертыванию
  • Обучение администратора работе с корзиной
  • Поддержка в течение 30 дней после запуска

Процесс работы

  1. Аналитика и аудит. Изучаем текущую реализацию корзины, выявляем узкие места.
  2. Проектирование API. Согласовываем структуру эндпоинтов и формат данных.
  3. Разработка React-компонентов. Реализуем стор, компоненты и интеграцию с бэкендом.
  4. Интеграция с 1С-Битрикс. Настраиваем роутинг, синхронизацию и обработку ошибок.
  5. Тестирование. Проверяем сценарии: добавление, удаление, купоны, авторизация, мобильные устройства.
  6. Деплой и поддержка. Разворачиваем на боевом сервере, предоставляем доступ к исходному коду и документации.

Чек-лист типичных ошибок

  • Не проверены остатки (maxQuantity). Если товара нет на складе, корзина должна показать сообщение и не давать добавить больше.
  • Игнорирование слияния корзин. При авторизации корзина анонима может потеряться, если не вызвать объединение.
  • Отсутствие обработки ошибок. Ошибка сети не должна приводить к зависанию интерфейса — откатывайте изменения.

Сроки и стоимость

Сроки разработки: от 2 до 4 недель в зависимости от сложности каталога и требований к дизайну. Стоимость рассчитывается индивидуально после аудита текущего магазина.

Свяжитесь с нами, чтобы обсудить ваш проект. Закажите предварительную консультацию — мы пришлём примерное коммерческое предложение в течение дня. Получите консультацию: напишите нам, и мы оценим, как React-корзина может улучшить ваш интернет-магазин.

Этап Длительность Результат
Аналитика и аудит 1–2 дня Отчёт с рекомендациями
Разработка API и React-корзины 5–10 дней Исходный код, документация
Интеграция и тестирование 3–5 дней Рабочий прототип на staging
Деплой и финальное тестирование 2–3 дня Продакшн-версия

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1543
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060
  • Разработка виджета онлайн-записи на прием для медицинского центра
    Разработка виджета онлайн-записи на прием для медицинского центра
    837
  • Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    928
  • Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    865
  • Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    1223