Guía de React
Aprende a crear sliders con @reelkit/react.
Componente Reel
El componente Reel es el contenedor principal: gestiona el estado del slider, los gestos táctiles, la navegación con teclado y las animaciones.
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>Tamaño automático
La prop size es opcional. Sin ella, Reel mide su contenedor con ResizeObserver y se adapta al diseño que marque el CSS. El tamaño del contenedor lo tiene que dar su padre (por ejemplo, flex, grid o dimensiones explícitas en CSS).
// 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={...} />Patrón itemBuilder
La prop itemBuilder es una función que recibe el índice y devuelve el contenido de cada slide. Este patrón hace posible la virtualización: solo se renderizan los elementos visibles.
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} />;
}}Navegación
Métodos de navegación incluidos:
- Táctil / deslizar: arrastra para navegar con inercia y ajuste al slide
- Teclado: teclas de flecha y Escape
- Rueda del ratón: se activa con la prop
enableWheel - Por código: usa
apiRefparanext(),prev(),goTo()
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>
</>
);
}Estado en la URL
useOverlayUrlState crea un controlador de estado en la URL para un overlay y lo devuelve entero; después se lo pasas a un *UrlOverlay en su prop controller. La URL es dueña del estado abierto, así que un overlay vinculado se abre solo y lo habitual es abrirlo con un enlace. La primera escritura de un parámetro ausente añade una entrada al historial y las siguientes la sustituyen, así que pasar slides nunca entierra el botón de volver. Guarda el controlador para leer value/position y manejarlo por código: set(position) abre, set(null) cierra, y set es la misma escritura de bajo nivel que usa el overlay internamente al cambiar de slide.
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),
});El objeto de opciones recibe param, codec y locator (los tres obligatorios), más un adapter opcional. param y adapter se leen en el primer renderizado y quedan fijos (vuelve a montar para cambiarlos), mientras que codec y locator se leen en cada uso, así que una búsqueda después de que la lista crezca o se reordene ve la lista actual. El codec y el locator son un par a juego que comparte el mismo Id, así que van juntos: para una galería simple con ?photo=3, usa ...urlIndexKey(() => images.length), que devuelve las dos mitades a la vez. urlIndexKey convierte el parámetro en el índice de un slide y lo limita con el recuento actual que devuelve el getter, así que un ?photo=99 desfasado o fuera de rango se rechaza y se limpia solo de la URL en lugar de abrir un slide que nunca se nombró. Pasa un getter y no un número para que el límite siga siendo correcto mientras crece un feed paginado. Envuelve createIndexLocator (la mitad del locator) y lo combina con indexCodec. Un feed paginado o una galería por identidad aporta su propio par de codec + locator. La tabla completa de opciones está en la referencia de la API de React.
ReelIndicator
Componente opcional que muestra indicadores de progreso al estilo de Instagram con la posición actual en el slider. Colocado dentro de un Reel, se conecta solo a los valores count y active del padre a través del contexto, sin conectar el estado a mano.
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} />Demo en vivo: slider básico
Pruébalo: pulsa los botones para moverte entre los slides.
Puntos clave
- Prop size
Tupla opcional [width, height], u omítela para que el CSS marque el tamaño
- itemBuilder
Recibe el índice y devuelve el contenido del slide
- apiRef
Da acceso a los métodos del controlador para navegar
- afterChange
Sigue el índice actual para actualizar la interfaz
Demo en vivo: lista infinita
reelkit renderiza solo 3 slides en el DOM en todo momento (el actual, el anterior y el siguiente). Así el desplazamiento es fluido en listas de más de 10.000 elementos.
10.000 elementos y solo 3 en el DOM. Usa los botones o escribe un número para saltar.
Demo en vivo: lista que crece
Simula un feed infinito en el que los elementos se cargan bajo demanda, como en TikTok o Instagram. Empieza con 20 elementos; desplázate cerca del final y verás llegar nuevos lotes automáticamente.
Desplázate hasta el final: los nuevos elementos se cargan solos. El contador y el indicador crecen a medida que llegan los lotes.
Consejos de rendimiento
- Memoriza los arrays de datos
Envuelve el array de elementos con
useMemo. Una referencia nueva en cada renderizado provoca una actualización decounty un nuevo cálculo de los rangos visibles. - Mantén itemBuilder ligero
Se ejecuta con cada cambio del rango visible (normalmente 3 slides). Evita dentro cálculos pesados o efectos secundarios.
- Carga datos cerca del final
Usa
afterChangepara detectar cuándo el usuario se acerca al final y pide el siguiente lote antes de que se quede sin slides (mira la demo de la lista que crece más arriba). - Desactiva la rueda en páginas con scroll
Pon
enableWheel={false}cuando el slider esté dentro de un diseño con scroll para no capturar el desplazamiento de la página.
Siguientes pasos
- Referencia de la API - todas las props disponibles
- Reel Player - reproductor de vídeo al estilo de TikTok/Reels
- Lightbox - galería de imágenes y vídeos
- Stories Player - visor de stories al estilo de Instagram
