---
title: "API Reference"
description: "Public API reference for react-native-reanimated-carousel v5"
canonical_url: "https://rn-carousel.dev/props"
markdown_url: "https://rn-carousel.dev/props.md"
version: "5"
---
# API Reference

v5 exposes two runtime components and a deliberate type whitelist:

```ts
import {
  Carousel,
  Pagination,
  type CarouselAnimation,
  type CarouselItemAnimation,
  type CarouselLayout,
  type CarouselPanGesture,
  type CarouselProgressChangeHandler,
  type CarouselProps,
  type CarouselRef,
  type CarouselRenderItem,
  type CarouselRenderItemInfo,
  type CarouselScrollToOptions,
  type CarouselStepOptions,
  type PaginationDotStyle,
  type PaginationProps,
} from "react-native-reanimated-carousel";
```

There is no default export and package deep imports are unsupported.

## Carousel

```tsx
<Carousel
  data={items}
  renderItem={({ item }) => <Slide item={item} />}
/>
```

### Data and selection

| Prop | Type | Default | Description |
|---|---|---|---|
| `data` | `Item[]` | required | Raw application data. All public indices refer to this array. |
| `renderItem` | `CarouselRenderItem` | required | JS-thread renderer for each mounted slide. |
| `keyExtractor` | `(item, index) => string` | — | Stable identity used to preserve selection across data updates. |
| `defaultIndex` | `number` | `0` | Mount-only initial raw-data index. |
| `loop` | `boolean` | `false` | Enables infinite logical wrapping. |

An empty `data` array is valid and produces neutral index/progress/offset values of `0`. Navigation and lifecycle callbacks are no-ops. With non-empty data, `defaultIndex` must be an in-range integer.

When data changes, a matching `keyExtractor` key remains selected. Otherwise the previous numeric index is clamped. Reconciliation waits for active movement to settle and does not emit lifecycle callbacks.

### Size, orientation, and rendering

| Prop | Type | Default | Description |
|---|---|---|---|
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Logical main axis. |
| `itemSize` | `number` | container main-axis size | Page distance used by snapping and progress. Must be positive. |
| `renderWindowSize` | `number` | all slides | Maximum mounted slides including the current slide. Must be a positive integer. |
| `style` | `StyleProp` | `{}` | Root viewport style and container dimensions. |
| `contentContainerStyle` | `StyleProp` | `{}` | Inner content layer. `opacity` and `transform` are library-owned. |
| `testID` | `string` | — | Applied to the root viewport. |
| `onLayout` | `(event: LayoutChangeEvent) => void` | — | Root viewport layout callback. |

Use `style` for the viewport and `itemSize` only when the page distance differs from its main-axis size:

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

If `renderWindowSize` is omitted, all raw slides are mounted. It affects mounting only, not navigation or progress.

### Scrolling and snapping

| Prop | Type | Default | Description |
|---|---|---|---|
| `scrollEnabled` | `boolean` | `true` | Enables user pan gestures. It does not stop autoplay or ref commands. |
| `snapMode` | `"page" \| "nearest" \| "none"` | `"page"` | Single-page snap, nearest-page snap, or free decay. |
| `snapMomentum` | `number` | `2` | Seconds of release velocity added before `snapMode="nearest"` picks a page. `0` snaps to the page under the finger. Throws when negative or not finite. |
| `overscrollEnabled` | `boolean` | `true` | Enables resisted overdrag and rebound when `loop={false}`. |
| `animation` | `CarouselAnimation` | timing, `500ms` | Transition config for gesture snapping, commands, and autoplay. |
| `onConfigurePanGesture` | `(gesture: CarouselPanGesture) => void` | — | Configures thresholds, pointers, relationships, and worklet observers. |

Timing and spring configs are flat discriminated unions:

```tsx
<Carousel animation={{ type: "timing", duration: 350 }} />

<Carousel
  animation={{
    type: "spring",
    damping: 18,
    stiffness: 180,
  }}
/>
```

`snapMode="none"` decay and overscroll rebound use internal physics. Reanimated's system reduce-motion behavior remains active.

`CarouselPanGesture` is a narrow facade over the real Gesture Handler pan gesture. It includes:

- activation/failure offsets, distance, velocity, pointer count, hit slop, mouse, and trackpad configuration;
- simultaneous, require-to-fail, and blocking external relationships;
- `onBegin`, `onStart`, `onUpdate`, `onChange`, `onEnd`, and `onFinalize` worklet observers.

It intentionally excludes `enabled`, `runOnJS`, and `manualActivation`. Use `scrollEnabled` for gesture enablement and `scheduleOnRN` for JS side effects. Carousel-owned handlers run before consumer observers.

### Autoplay

| Prop | Type | Default | Description |
|---|---|---|---|
| `autoplay` | `boolean` | `false` | Controlled autoplay switch. |
| `autoplayInterval` | `number` | `3000` | Idle dwell in milliseconds after one transition settles. |
| `autoplayDirection` | `"forward" \| "backward"` | `"forward"` | Logical raw-data direction. |

The interval does not include animation time. Autoplay pauses during active gestures and transitions, then restarts its dwell after settle. With `loop={false}`, it stops at the logical boundary.

### Progress and advanced offset

| Prop | Type | Thread | Description |
|---|---|---|---|
| `progress` | `SharedValue` | UI | Fractional logical index, written by Carousel every frame. |
| `onProgressChange` | `(progress: number) => void` | JS | Per-frame logical progress callback. |
| `scrollOffsetValue` | `SharedValue` | UI | Advanced two-way signed main-axis translation in pixels. |

Progress moves `+1` in logical forward order and `-1` backward. Non-loop progress is bounded to `[0, count - 1]`; loop progress is continuous and unbounded. Its positive modulo by `count` identifies the settled raw index.

Offset is `0` at item `0`; moving forward one page changes it by `-itemSize`. This sign is stable across horizontal, vertical, LTR, and RTL.

`progress` is consumer-read-only. Prefer it for UI-thread work; `onProgressChange` crosses to JS every frame and should stay light. `scrollOffsetValue` is intentionally writable, but an external write only moves content—it does not commit selection or fire `onSnapToItem`.

### Item animation and layouts

`layout` and `itemAnimation` are a TypeScript XOR: supply at most one.

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

`CarouselLayout` supports:

```ts
type CarouselLayout =
  | {
      type: "parallax";
      offset?: number;        // 100
      scale?: number;         // 0.8
      adjacentScale?: number; // scale ** 2
    }
  | {
      type: "horizontal-stack" | "vertical-stack";
      visibleCount?: number;  // raw data length - 1
      exitDistance?: number;  // screen width
      spacing?: number;       // 18
      scaleStep?: number;     // 0.04
      opacityStep?: number;   // 0.1
      rotation?: number;      // 30 degrees
      exitDirection?: "left" | "right"; // physical, default "left"
    };
```

For a custom effect:

```tsx
const itemAnimation: CarouselItemAnimation = (relativeProgress) => {
  "worklet";
  return {
    opacity: Math.max(0, 1 - Math.abs(relativeProgress)),
  };
};

<Carousel itemAnimation={itemAnimation} data={items} renderItem={renderItem} />
```

`relativeProgress` is logical: `0` is selected, positive values are forward, negative values are backward, and fractions represent motion. Direction-sensitive `translateX` values returned by a custom animation are physical; custom horizontal RTL effects must mirror those values when appropriate.

### Lifecycle callbacks

| Prop | Type | Description |
|---|---|---|
| `onScrollStart` | `() => void` | JS callback once when an accepted gesture, command, or autoplay transition starts. |
| `onSnapToItem` | `(index: number) => void` | JS callback when movement settles, with the raw-data index. |

Rejected/no-op commands, direct offset writes, relayout, and data reconciliation do not fire lifecycle callbacks. An accepted non-animated command emits start and then immediately emits settled.

`onScrollStart` is not a user-touch detector because autoplay also fires it. Use an `onBegin` gesture observer when that distinction matters.

### Render item

```ts
interface CarouselRenderItemInfo<Item> {
  item: Item;
  index: number;
  relativeProgress: SharedValue<number>;
}
```

`renderItem` executes on the JS thread. `relativeProgress` is consumed from worklets or animated styles.

## Carousel ref

```ts
interface CarouselRef {
  prev(options?: CarouselStepOptions): void;
  next(options?: CarouselStepOptions): void;
  getCurrentIndex(): number;
  scrollTo(options: CarouselScrollToOptions): void;
}

interface CarouselStepOptions {
  count?: number;
  animated?: boolean;
}

interface CarouselScrollToOptions {
  index: number;
  animated?: boolean;
}
```

- `next` and `prev` use `count: 1` and `animated: true` by default.
- `count` must be a positive integer. `0` is a no-op.
- `scrollTo` requires an in-range raw-data index and defaults to animated.
- In loop mode, `scrollTo` takes the shortest route and chooses logical forward on an exact tie.
- `getCurrentIndex()` returns the last settled raw-data index, including during an in-flight transition.

## Pagination

```tsx
<Pagination count={items.length} progress={progress} />
```

| Prop | Type | Default | Description |
|---|---|---|---|
| `count` | `number` | required | Non-negative integer number of raw-data dots. |
| `progress` | read-only `SharedValue` | required | Same logical progress produced by Carousel. |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Horizontal start-edge order or vertical top-to-bottom order. |
| `containerStyle` | `StyleProp` | — | Outer style; cannot override `direction` or `flexDirection`. |
| `dotStyle` | `PaginationDotStyle` | `10 × 10` gray dot | Base dot style. |
| `activeDotStyle` | `PaginationDotStyle` | dark base-size dot | Active style inheriting omitted base fields. |
| `onPress` | `(index: number) => void` | — | Makes dots focusable buttons and receives a raw-data index. |
| `getItemAccessibilityLabel` | `(index, count) => string` | `Slide N of M` | Only valid when `onPress` is present. |

`PaginationDotStyle` includes numeric `width`, `height`, `borderRadius`, `borderWidth`, `opacity`, plus `borderColor` and `backgroundColor`. The component reserves the larger active/base dimensions to avoid layout shift.

Loop progress needs no `loop` prop: each dot compares itself with the nearest equivalent `index + k * count`. `count={0}` renders nothing; `count={1}` keeps the only dot selected.

With `onPress`, each item is an accessible button with selected state. Without it, dots are decorative and hidden from the accessibility tree.

## Accessibility

Carousel hides non-current slides from the accessibility tree. The application owns semantics inside `renderItem` and can compose headings, regions, external navigation buttons, or an interactive Pagination around the viewport.

Avoid making a slide's outer wrapper an accessible group when it contains separately focusable controls: React Native may group descendants and change their focus behavior.

## Thread boundaries

UI-thread/worklet surfaces:

- `progress`, `scrollOffsetValue`, and `relativeProgress`;
- `itemAnimation`;
- gesture observer callbacks;
- Pagination dot interpolation.

JS-thread surfaces:

- `renderItem`, `keyExtractor`, and the `onConfigurePanGesture` configuration call;
- lifecycle and progress callbacks;
- ref calls, `onLayout`, Pagination `onPress`, and accessibility labels.
