Быстрая фильтрация и умный поиск: React-каталог для 1С-Битрикс

Каталог — самая нагруженная часть интернет-магазина: фильтрация, сортировка, пагинация, быстрый просмотр, добавление в корзину. Стандартный компонент `bitrix:catalog` при каждом изменении фильтра делает полный перезапрос страницы с серверным рендерингом, что занимает 1.5–3 секунды. Представьте катал
Услуги, которые мы предлагаем
Показано 1 из 1Все 1626 услуг
Быстрая фильтрация и умный поиск: React-каталог для 1С-Битрикс
Средний
~1-2 недели

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

Часто задаваемые вопросы

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

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1415
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    995
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    733
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    863
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    772
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    1134

Каталог — самая нагруженная часть интернет-магазина: фильтрация, сортировка, пагинация, быстрый просмотр, добавление в корзину. Стандартный компонент bitrix:catalog при каждом изменении фильтра делает полный перезапрос страницы с серверным рендерингом, что занимает 1.5–3 секунды. Представьте каталог с 50 000 товаров — каждый клик фильтра означает потерю времени и нервов покупателя. Мы разрабатываем React-каталог, который даёт мгновенную реакцию на действия пользователя: страница загружается за 200–400 мс, смена фильтра занимает до 300 мс. Разница в UX ощутима сразу: конверсия в корзину растёт на 15–30%. Наш опыт — более 5 лет и 50+ проектов на стыке Битрикса и React.

Почему React вместо стандартного каталога?

Браузерный рендеринг избавляет от полных перезапросов. Каждое изменение фильтра — это асинхронный запрос к REST API, а не перезагрузка страницы. Бэкенд использует тегированное кэширование: при изменении товара сбрасывается только кэш, связанный с этим товаром, а не весь каталог. Результат: плавные анимации, сохранение состояния фильтров в URL, возможность поделиться ссылкой на конкретную выдачу. Пользователи проводят больше времени в каталоге, конверсия увеличивается.

Как работает API для каталога?

Бэкенд на PHP отдаёт данные каталога в JSON. Базовый контроллер обрабатывает запросы с фильтрами, сортировкой и пагинацией:

// /local/ajax/api.php — обработчик catalog.list case 'catalog.list': CModule::IncludeModule('iblock'); CModule::IncludeModule('catalog'); $filter = [ 'IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y', 'SECTION_ID'=> (int)$_GET['section_id'], ]; // Ценовые фильтры if (!empty($_GET['price_from'])) { $filter['>=CATALOG_PRICE_1'] = (float)$_GET['price_from']; } if (!empty($_GET['price_to'])) { $filter['<=CATALOG_PRICE_1'] = (float)$_GET['price_to']; } // Фильтр по свойствам if (!empty($_GET['props'])) { $props = json_decode($_GET['props'], true); foreach ($props as $propCode => $values) { $filter['PROPERTY_' . $propCode] = $values; } } $sort = match($_GET['sort'] ?? 'default') { 'price_asc' => ['CATALOG_PRICE_1' => 'ASC'], 'price_desc' => ['CATALOG_PRICE_1' => 'DESC'], 'new' => ['DATE_CREATE' => 'DESC'], default => ['SORT' => 'ASC'], }; $page = max(1, (int)($_GET['page'] ?? 1)); $limit = 24; $res = CIBlockElement::GetList( $sort, $filter, false, ['iNumPage' => $page, 'nPageSize' => $limit], ['ID', 'NAME', 'PREVIEW_PICTURE', 'DETAIL_PAGE_URL', 'PROPERTY_ARTICLE', 'CATALOG_PRICE_1'] ); $items = []; while ($el = $res->GetNext()) { $items[] = [ 'id' => $el['ID'], 'name' => $el['NAME'], 'slug' => $el['CODE'], 'price' => (float)$el['CATALOG_PRICE_1'], 'image' => CFile::GetPath($el['PREVIEW_PICTURE']), 'url' => $el['DETAIL_PAGE_URL'], ]; } echo json_encode([ 'result' => $items, 'total' => $res->SelectedRowsCount(), 'pages' => ceil($res->SelectedRowsCount() / $limit), ]); break; 

React-компонент каталога с фильтрами

На фронтенде используем хук useSearchParams для синхронизации фильтров с URL. Каждый фильтр — это параметр строки запроса, поэтому ссылку на конкретную выдачу можно скопировать и отправить коллеге.

// CatalogPage.tsx import { useState, useCallback } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useSearchParams } from 'react-router-dom'; interface CatalogFilters { priceFrom?: number; priceTo?: number; props: Record<string, string[]>; sort: string; page: number; } export function CatalogPage({ sectionId }: { sectionId: number }) { const [searchParams, setSearchParams] = useSearchParams(); const filters: CatalogFilters = { priceFrom: searchParams.get('price_from') ? Number(searchParams.get('price_from')) : undefined, priceTo: searchParams.get('price_to') ? Number(searchParams.get('price_to')) : undefined, props: JSON.parse(searchParams.get('props') || '{}'), sort: searchParams.get('sort') || 'default', page: Number(searchParams.get('page') || 1), }; const { data, isLoading } = useQuery({ queryKey: ['catalog', sectionId, filters], queryFn: () => fetchCatalog(sectionId, filters), keepPreviousData: true, }); const updateFilter = useCallback((key: string, value: string | null) => { setSearchParams(prev => { if (value) prev.set(key, value); else prev.delete(key); prev.delete('page'); return prev; }); }, [setSearchParams]); return ( <div className="catalog-layout"> <CatalogFilters filters={filters} onFilterChange={updateFilter} /> <div className="catalog-main"> <CatalogToolbar total={data?.total} sort={filters.sort} onSortChange={v => updateFilter('sort', v)} /> {isLoading ? ( <ProductGrid items={Array(24).fill(null)} skeleton /> ) : ( <ProductGrid items={data?.items || []} /> )} <Pagination current={filters.page} total={data?.pages || 1} onChange={p => updateFilter('page', String(p))} /> </div> </div> ); } 

Фильтры синхронизируются с URL через useSearchParams — это позволяет поделиться ссылкой на конкретную фильтрацию и корректно работать с кнопкой «назад» в браузере.

Что даёт умный фильтр?

Стандартный компонент bitrix:catalog.smart.filter генерирует HTML, непригодный для React. Для кастомного фильтра нужен API умного фильтра:

// catalog.filter.get — доступные значения фильтров для текущего раздела case 'catalog.filter.get': // Получаем доступные свойства и их значения // с учётом текущих выбранных фильтров (для зависимых фильтров) $availableProps = getSmartFilterProps( CATALOG_IBLOCK_ID, (int)$_GET['section_id'], json_decode($_GET['selected'] ?? '{}', true) ); echo json_encode(['result' => $availableProps]); break; 

Зависимые фильтры (когда выбор одного значения сужает доступные значения другого) — сложная задача. Реализуется через повторный запрос к API при изменении любого фильтра с передачей текущего выбора. Такой подход обеспечивает поведение, аналогичное стандартному умному фильтру, но в SPA-стиле. Дополнительно мы используем HL-блоки для хранения пользовательских предпочтений, что ускоряет повторные визиты.

Когда стоит переходить на React-каталог?

Если ваш каталог содержит более 10 000 товаров, имеет сложные фильтры с зависимостями или вы замечаете падение конверсии на мобильных устройствах — React-каталог решит эти проблемы. Скорость работы напрямую влияет на выручку: каждая секунда задержки снижает конверсию на 7%. Full-stack подход (PHP + React) даёт гибкость при интеграции с 1С через CommerceML.

Оптимизация производительности

Метод Серверный рендеринг React-каталог
Первая загрузка 1.5–3 с 0.2–0.4 с
Смена фильтра 1.5–3 с (релоад) 0.1–0.3 с
Добавление в корзину 0.5–1 с 0.1–0.2 с
Сохранение состояния нет да

Виртуализация списка. При показе 100+ товаров используйте @tanstack/react-virtual — рендерится только видимая область. Это снижает потребление памяти и ускоряет скролл.

import { useVirtual } from '@tanstack/react-virtual'; const rowVirtualizer = useVirtual({ count: items.length, parentRef: containerRef, estimateSize: () => 350, }); 

Prefetch следующей страницы. При скролле к последней видимой строке предзагружайте следующую страницу:

useEffect(() => { if (isNearEnd && data?.pages > filters.page) { queryClient.prefetchQuery( ['catalog', sectionId, { ...filters, page: filters.page + 1 }], () => fetchCatalog(sectionId, { ...filters, page: filters.page + 1 }) ); } }, [isNearEnd]); 

Изображения. Lazy loading через loading="lazy" + современные форматы (WebP через Битрикс \Bitrix\Main\Web\Uri + конвертер или внешний CDN). Для skeleton-заглушек при загрузке используйте CSS-анимацию — дешевле, чем JavaScript-анимации.

Этапы разработки React-каталога

Чек-лист внедрения:

  • Анализ инфоблоков и свойств, проектирование API.
  • Разработка API-контроллеров (список, фильтры, пагинация).
  • Создание React-компонентов (фильтр, сетка, пагинация, скелетоны).
  • Интеграция с торговым каталогом и обменом с 1С через CommerceML.
  • Настройка тегированного кэширования и HTTP-кэша.
  • Тестирование на реальных данных, замеры производительности.
  • Подготовка документации и обучение команды заказчика.

Процесс включает аналитику, проектирование API, разработку фронтенда и бэкенда, интеграцию с 1С и тестирование. Каждый этап завершается демонстрацией заказчику.

Этап Длительность Результат
Анализ 3–5 дней Техническое задание и прототип API
Разработка API 5–10 дней Готовые эндпоинты
Фронтенд 7–14 дней Рабочий каталог с фильтрами
Интеграция 3–5 дней Полная совместимость с 1С
Тестирование 2–4 дня Отчёт о производительности

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

  • API-контроллеры для списка товаров, фильтров, пагинации.
  • React-компоненты: фильтр, сетка товаров, пагинация, скелетоны.
  • Интеграция с существующими инфоблоками, торговым каталогом, 1С.
  • Настройка кэширования (тегированное кэширование, HTTP-кэш).
  • Документация по API и архитектуре.
  • Обучение ваших разработчиков (до 2 часов).

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