---
title: "Usage"
description: "Get started with react-native-reanimated-carousel v5"
canonical_url: "https://rn-carousel.dev/usage"
markdown_url: "https://rn-carousel.dev/usage.md"
version: "5"
---
# Usage

Wrap your application in Gesture Handler's root view, then render the named `Carousel` export:

```tsx
import * as React from "react";
import { Text, useWindowDimensions, View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { Carousel } from "react-native-reanimated-carousel";

const data = ["One", "Two", "Three"];

export default function App() {
  const { width } = useWindowDimensions();

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <View style={{ flex: 1, justifyContent: "center" }}>
        <Carousel
          data={data}
          style={{ width, height: 220 }}
          renderItem={({ item, index }) => (
            <View
              style={{
                flex: 1,
                alignItems: "center",
                justifyContent: "center",
                backgroundColor: index % 2 ? "#DCE7F7" : "#F5E7D3",
              }}
            >
              <Text>{item}</Text>
            </View>
          )}
        />
      </View>
    </GestureHandlerRootView>
  );
}
```

`loop` defaults to `false`. Add `loop` explicitly for infinite wrapping.

## Sizing

`style` controls the viewport. If `itemSize` is omitted, the page distance is the measured main-axis size.

### Fixed size

```tsx
<Carousel
  style={{ width: 320, height: 180 }}
  data={data}
  renderItem={renderItem}
/>
```

### Responsive size

The parent must provide enough constraints for the viewport to measure:

```tsx
<View style={{ height: 220 }}>
  <Carousel
    style={{ flex: 1 }}
    data={data}
    renderItem={renderItem}
  />
</View>
```

### Multiple visible items

Set `itemSize` when the snap distance should be smaller than the viewport:

```tsx
<Carousel
  style={{ width: 360, height: 180 }}
  itemSize={240}
  data={data}
  renderItem={renderItem}
/>
```

For a vertical carousel, use the same prop names:

```tsx
<Carousel
  orientation="vertical"
  style={{ width: 240, height: 480 }}
  itemSize={180}
  data={data}
  renderItem={renderItem}
/>
```

## Pagination

Create one logical progress SharedValue and give it to both components:

```tsx
import * as React from "react";
import { View } from "react-native";
import { useSharedValue } from "react-native-reanimated";
import {
  Carousel,
  Pagination,
  type CarouselRef,
} from "react-native-reanimated-carousel";

function CarouselWithPagination() {
  const ref = React.useRef<CarouselRef>(null);
  const progress = useSharedValue(0);
  const data = ["One", "Two", "Three"];

  return (
    <View>
      <Carousel
        ref={ref}
        data={data}
        progress={progress}
        style={{ height: 220 }}
        renderItem={renderItem}
      />

      <Pagination
        count={data.length}
        progress={progress}
        containerStyle={{ gap: 8, justifyContent: "center", marginTop: 12 }}
        dotStyle={{ width: 8, height: 8, backgroundColor: "#CBD5E1" }}
        activeDotStyle={{ width: 20, backgroundColor: "#0F172A" }}
        onPress={(index) => ref.current?.scrollTo({ index })}
        getItemAccessibilityLabel={(index, count) =>
          `Featured item ${index + 1} of ${count}`
        }
      />
    </View>
  );
}
```

With `onPress`, Pagination dots are accessible buttons. Without `onPress`, they are decorative and removed from the accessibility tree.

## Progress

`progress` is the UI-thread option. It is a fractional logical index:

- item `0` is progress `0`;
- moving forward increases progress;
- non-loop progress is bounded;
- loop progress is continuous and can cross multiple cycles.

Use `onProgressChange` only when JS needs each frame:

```tsx
<Carousel
  data={data}
  renderItem={renderItem}
  onProgressChange={(progress) => {
    // Runs on JS. Keep this work small.
  }}
/>
```

Pixel translation is a separate advanced surface:

```tsx
const offset = useSharedValue(0);

<Carousel
  data={data}
  renderItem={renderItem}
  scrollOffsetValue={offset}
/>
```

Forward one page is `-itemSize` pixels. External writes move the content but do not commit selection; call `scrollTo({ index })` to settle on an item.

## Layouts

Built-in layouts use one flat discriminated object:

```tsx
<Carousel
  data={data}
  renderItem={renderItem}
  layout={{
    type: "parallax",
    offset: 100,
    scale: 0.8,
  }}
/>
```

Stack:

```tsx
<Carousel
  data={data}
  renderItem={renderItem}
  layout={{
    type: "horizontal-stack",
    visibleCount: 4,
    spacing: 18,
    exitDirection: "left",
  }}
/>
```

For custom effects, use `itemAnimation` instead of `layout`; TypeScript prevents passing both.

## Autoplay

```tsx
<Carousel
  data={data}
  renderItem={renderItem}
  loop
  autoplay
  autoplayInterval={3000}
  autoplayDirection="forward"
/>
```

`autoplayInterval` is settled dwell time: animation duration is not part of the interval. When `loop={false}`, autoplay stops at the boundary.

`scrollEnabled={false}` disables user gestures only. Autoplay and ref commands remain available.

## Accessibility

Only the current slide is exposed to accessibility services. Provide meaningful slide content inside `renderItem` and compose external headings, navigation buttons, or an interactive Pagination where appropriate.
