Посібник для React

Дізнайтеся, як будувати слайдери з @reelkit/react.

Спершу дотик
Свайп з інерцією та прилипанням
Навігація з клавіатури
Стрілки + Escape
Прокручування колесом
Необов’язково, з дебаунсом
Віртуалізований
10 000+ елементів, 3 у DOM
Indicators
Прокручування точок у стилі Instagram
Програмний API
next(), prev(), goTo() через ref
Режим циклу
Нескінченна кругова навігація
Directional
Вертикально або горизонтально
Жодних зайвих рендерів
Оновлення стану на сигналах

Компонент Reel

The Reel — головний контейнер: він тримає стан слайдера, обробляє дотикові жести, навігацію з клавіатури та анімації.

У DOM завжди лише три слайди, поточний і два сусідні, тож список із десяти тисяч елементів коштує стільки ж, скільки список із десяти. Щоб побачити це в цілій функції, як-от нескінченна стрічка чи сітка, що відкриває плеєр, перейдіть до Рецептів.

tsx
import { Reel, ReelIndicator } from '@reelkit/react';

<Reel
  count={items.length}
  size={[width, height]}
  direction="vertical"
  enableWheel
  afterChange={(index) => console.log('Current:', index)}
  itemBuilder={(index, indexInRange, size) => (
    <div style={{ width: size[0], height: size[1] }}>
      Slide {index}
    </div>
  )}
>
  {/* Optional children like ReelIndicator */}
</Reel>

Auto-sizing

The size необов’язковий. Якщо його не передати, Reel сам вимірює контейнер через ResizeObserver і підлаштовується під макет, заданий CSS. Розмір контейнера має задавати батьківський елемент — наприклад, flex, grid або явні розміри в CSS.

tsx
// Explicit size (fixed)
<Reel count={items.length} size={[400, 600]} itemBuilder={...} />

// Auto-size (responsive — sized by CSS)
<Reel count={items.length} style={{ width: '100%', height: '100dvh' }} itemBuilder={...} />

Патерн itemBuilder

The itemBuilder — функція, яка отримує індекс і повертає вміст слайда. Саме цей патерн дає віртуалізацію: рендеряться лише видимі елементи.

tsx
itemBuilder={(index, indexInRange, size) => {
  // index: actual item index (0 to count-1)
  // indexInRange: position in visible window (0, 1, or 2)
  // size: [width, height] of the container
  return <Slide index={index} />;
}}

Вбудовані способи навігації:

  • Дотик / свайп: Тягніть, щоб гортати — з інерцією та прилипанням
  • Клавіатура: Стрілки та Escape
  • Колесо миші: Увімкніть enableWheel у пропсах
  • Програмно: Використовуйте apiRef для next(), prev(), goTo()
tsx
import { useRef } from 'react';
import { Reel, type ReelApi } from '@reelkit/react';

function App() {
  const apiRef = useRef<ReelApi>(null);

  return (
    <>
      <Reel
        count={10}
        size={[400, 600]}
        apiRef={apiRef}
        itemBuilder={(index) => <Slide index={index} />}
      />
      <button onClick={() => apiRef.current?.prev()}>Prev</button>
      <button onClick={() => apiRef.current?.next()}>Next</button>
      <button onClick={() => apiRef.current?.goTo(5)}>Go to 5</button>
    </>
  );
}

Стан в URL

useOverlayUrlState будує контролер стану в URL для оверлея й повертає його цілком, а ви передаєте його в *UrlOverlay як його controller . Стан відкриття належить URL, тож прив’язаний оверлей відкривається сам, а посилання — звичайний спосіб його відкрити. Перший запис відсутнього параметра додає один запис в історію, кожен наступний його замінює, тож гортання ніколи не ховає кнопку «назад». Тримайте контролер, щоб читати value/позицією і керувати ним програмно: set(position) відкриває, set(null) закриває, а set — той самий низькорівневий запис, який оверлей робить усередині під час зміни слайда.

tsx
import { useOverlayUrlState, urlIndexKey } from '@reelkit/react';
import { useReactRouterUrlAdapter } from '@reelkit/react/react-router-url-adapter';
import { LightboxUrlOverlay } from '@reelkit/react-lightbox';
import { Link } from 'react-router-dom';

const photo = useOverlayUrlState({
  param: 'photo',
  ...urlIndexKey(() => images.length),
});

// Opening is a link — the overlay reads the URL and opens itself.
<Link to="?photo=3"><img src={images[3].src} /></Link>
<LightboxUrlOverlay controller={photo} images={images} />

// Read the url-derived state, or close programmatically (a low-level write).
photo.position.value; // 3 for ?photo=3, null when nothing is open
photo.set(null); // close

// Routed app: pass a router-backed adapter, otherwise the router's
// own location goes stale and its next navigation drops the param.
const adapter = useReactRouterUrlAdapter();
const routed = useOverlayUrlState({
  param: 'photo',
  adapter,
  ...urlIndexKey(() => images.length),
});

Об’єкт опцій приймає param, codec, та locator (усі три обов’язкові) плюс необов’язковий adapter. param та adapter читаються під час першого рендеру й далі не змінюються — щоб змінити їх, перемонтуйте компонент, — а codec та locator читаються наживо, тож пошук після того, як список виріс чи змінив порядок, бачить поточний список. codec та locator — узгоджена пара з однаковим Id, тож вони йдуть разом — для звичайної ?photo=3 галереї розгортайте ...urlIndexKey(() => images.length), який повертає обидві половини одразу. urlIndexKey зіставляє параметр з індексом слайда й обмежує його живою кількістю, яку повертає геттер, тож застарілий або позамежний ?photo=99 відхиляється й сам зникає з URL замість того, щоб відкрити слайд, якого ніхто не називав. Передавайте геттер, а не число, щоб межа лишалася правильною, поки посторінкова стрічка росте. Він загортає createIndexLocator (половину-локатор) і поєднує його з indexCodec. Посторінкова стрічка або галерея з адресацією за ідентичністю передає власну узгоджену пару codec + locator . Повна таблиця опцій — у довіднику API для React.

ReelIndicator

Необов’язковий компонент, що показує індикатори прогресу в стилі Instagram із поточною позицією в слайдері. Якщо він усередині Reel, він сам під’єднується до count та active значення через контекст — нічого зв’язувати вручну не треба.

tsx
import { Reel, ReelIndicator } from '@reelkit/react';

{/* Auto-connect: count and active are inherited from parent Reel */}
<Reel count={10} size={[400, 600]} itemBuilder={...}>
  <ReelIndicator />
</Reel>

{/* Manual usage: pass count and active explicitly (e.g. outside a Reel) */}
<ReelIndicator count={10} active={currentIndex} />

Головне

  • пропс size

    Необов’язковий кортеж [width, height] або пропустіть — розмір визначить CSS

  • itemBuilder

    Отримує індекс і повертає вміст слайда

  • apiRef

    Доступ до методів контролера для навігації

  • afterChange

    Стежить за поточним індексом для оновлення інтерфейсу

Поради щодо продуктивності

  • Мемоізуйте масиви даних

    Загортайте масив елементів у useMemo. Нове посилання на масив у кожному рендері спричиняє count оновлення й перерахунок видимих діапазонів.

  • Тримайте itemBuilder легким

    Він виконується на кожну зміну видимого діапазону (зазвичай 3 слайди). Уникайте важких обчислень і побічних ефектів усередині.

  • Вантажте дані ближче до краю

    Використовуйте afterChange щоб помітити наближення до кінця й підвантажити наступний пакет, доки слайди не скінчилися (дивіться рецепт Нескінченна стрічка).

  • Вимикайте колесо на сторінках із прокручуванням

    Set enableWheel={false} коли слайдер вбудований у макет із прокручуванням, щоб не перехоплювати прокручування сторінки.

Наступні кроки