Guia para React
Aprenda a montar sliders com @reelkit/react.
Componente Reel
O componente Reel é o contêiner principal: cuida do estado do slider, dos gestos de toque, da navegação por teclado e das animações.
Só três slides ficam no DOM, o atual e os vizinhos, então uma lista de dez mil itens custa o mesmo que uma de dez. Para ver isso funcionando em um recurso completo, como um feed infinito ou uma grade que abre um player, veja as Receitas.
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>Dimensionamento automático
A prop size é opcional. Sem ela, o Reel mede o próprio contêiner com ResizeObserver e acompanha o layout definido no CSS. O contêiner precisa ganhar tamanho do elemento pai (flex, grid ou dimensões explícitas no 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={...} />Padrão itemBuilder
A prop itemBuilder é uma função que recebe o índice e devolve o conteúdo de cada slide. Esse padrão é o que viabiliza a virtualização — apenas os itens visíveis são renderizados.
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} />;
}}Navegação
Formas de navegação já incluídas:
- Toque/Deslizar: arraste para navegar, com inércia e encaixe
- Teclado: setas e Escape
- Roda do mouse: ative pela prop
enableWheel - Programática: use
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 na URL
useOverlayUrlState monta um controlador de estado na URL para o overlay e devolve o controlador inteiro; você o entrega a um *UrlOverlay pela prop controller. Quem manda no estado aberto é a URL, então um overlay ligado a ela se abre sozinho e o link vira a forma normal de abrir. A primeira escrita de um parâmetro ausente empilha uma entrada no histórico e cada escrita seguinte a substitui, então percorrer os itens nunca soterra o botão voltar. Guarde o controlador para ler value/position e para conduzi-lo por código: set(position) abre, set(null) fecha, e set é exatamente a mesma escrita de baixo nível que o overlay usa internamente ao trocar 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),
});O objeto de opções recebe param, codec e locator (os três obrigatórios), mais um adapter opcional. param e adapter são lidos na primeira renderização e ficam fixos depois disso — remonte o componente para trocá-los —, enquanto codec e locator são lidos ao vivo, então uma busca feita depois de a lista crescer ou mudar de ordem enxerga a lista atual. O codec e o locator formam um par combinado que divide o mesmo Id, por isso andam juntos — em uma galeria simples com ?photo=3, espalhe ...urlIndexKey(() => images.length), que devolve as duas metades de uma vez. urlIndexKey liga o parâmetro a um índice de slide e o limita pela contagem atual que o getter devolve, então um ?photo=99 velho ou fora do intervalo é rejeitado e se cura sozinho saindo da URL, em vez de abrir um slide que ninguém nomeou. Passe um getter, e não um número, para que o limite continue certo à medida que um feed paginado cresce. Por baixo, ele embrulha createIndexLocator (a metade do locator) e a combina com indexCodec. Um feed paginado ou uma galeria endereçada por identidade fornece o próprio par codec + locator. A tabela completa de opções está na referência da API para React.
ReelIndicator
Componente opcional que mostra indicadores de progresso no estilo Instagram, sinalizando a posição atual dentro do slider. Colocado dentro de um Reel, ele se liga sozinho aos valores de count e active do componente pai pelo contexto — sem estado ligado à mão.
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} />Pontos principais
- prop size
Tupla [largura, altura] opcional; sem ela, o tamanho vem do CSS
- itemBuilder
Recebe o índice e devolve o conteúdo do slide
- apiRef
Dá acesso aos métodos do controlador para navegar
- afterChange
Acompanha o índice atual para atualizar a interface
Dicas de desempenho
- Memorize os arrays de dados
Envolva seu array de itens com
useMemo. Uma nova referência de array a cada renderização dispara uma atualização decounte o recálculo dos intervalos visíveis. - Deixe o itemBuilder leve
Ele roda a cada mudança do intervalo visível (normalmente 3 slides). Evite cálculos pesados ou efeitos colaterais lá dentro.
- Carregue os dados perto da borda
Use
afterChangepara perceber quando o leitor se aproxima do fim e busque o lote seguinte antes que os slides acabem (veja a receita Feed infinito). - Desligue a roda em páginas roláveis
Defina
enableWheel={false}quando o slider estiver dentro de um layout rolável, para não capturar a rolagem da página.
Próximos passos
- Referência da API - todas as props disponíveis
- Reel Player - player de vídeo no estilo TikTok/Reels
- Lightbox - galeria de imagens e vídeos
- Stories Player - visualizador de stories no estilo Instagram