Каталог — найнавантаженіша частина інтернет-магазину: фільтрація, сортування, пагінація, швидкий перегляд, додавання в кошик. Стандартний компонент bitrix:catalog при кожній зміні фільтра робить повний перезапит сторінки із серверним рендерингом (SSR), що займає 1.5–3 секунди. Уявіть каталог із 50 000 товарів — кожен клік фільтра означає втрату часу та нервів покупця. Ми розробляємо React-каталог, який дає миттєву реакцію на дії користувача: сторінка завантажується за 200–400 мс, зміна фільтра займає до 300 мс. Кожна секунда затримки знижує конверсію на 7%. Різниця в UX відчутна одразу: конверсія в кошик зростає на 15–30%. Наш досвід — понад 5 років та 50+ проектів на стику Бітрікса та React. Ми гарантуємо якість робіт та дотримання термінів. Команда має сертифікати 1С-Бітрікс. Гарантія на роботи — 6 місяців.
Переваги React-каталогу
Браузерний рендеринг (CSR) позбавляє повних перезапитів. Кожна зміна фільтра — це асинхронний запит до REST API, а не перезавантаження сторінки. Бекенд використовує теговане кешування: при зміні товару скидається лише кеш, пов'язаний із цим товаром, а не весь каталог. Результат: плавні анімації, збереження стану фільтрів в URL, можливість поділитися посиланням на конкретну видачу. Користувачі проводять більше часу в каталозі, конверсія збільшується. React-каталог завантажується в 7 разів швидше за стандартний, а зміна фільтра відбувається в 10 разів швидше.
Як працює 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-блоки для зберігання користувацьких уподобань, що прискорює повторні візити. Також застосовуємо бандл-спліттинг та code splitting для зменшення початкового завантаження.
Переваги 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-каталог для 1С-Бітрікс, який забезпечує швидку фільтрацію. Отримайте безкоштовну консультацію по вашому проекту — ми оцінимо обсяг робіт та запропонуємо оптимальне рішення. Замовте розробку React-каталогу та підвищте конверсію вашого магазину. Інвестиція від $5000 окупається за 3-6 місяців, забезпечуючи зростання прибутку на 15-30%.







