API Reference
v5 exposes two runtime components and a deliberate type whitelist:
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
<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<Item> | 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<ViewStyle> | {} | Root viewport style and container dimensions. |
contentContainerStyle | StyleProp<ViewStyle> | {} | 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:
<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. |
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:
<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, andonFinalizeworklet 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<number> | UI | Fractional logical index, written by Carousel every frame. |
onProgressChange | (progress: number) => void | JS | Per-frame logical progress callback. |
scrollOffsetValue | SharedValue<number> | 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.
<Carousel
layout={{ type: "parallax", offset: 100, scale: 0.8 }}
data={items}
renderItem={renderItem}
/>CarouselLayout supports:
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:
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
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
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;
}nextandprevusecount: 1andanimated: trueby default.countmust be a positive integer.0is a no-op.scrollTorequires an in-range raw-data index and defaults to animated.- In loop mode,
scrollTotakes 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
<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<number> | required | Same logical progress produced by Carousel. |
orientation | "horizontal" | "vertical" | "horizontal" | Horizontal start-edge order or vertical top-to-bottom order. |
containerStyle | StyleProp<ViewStyle> | — | 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, andrelativeProgress;itemAnimation;- gesture observer callbacks;
- Pagination dot interpolation.
JS-thread surfaces:
renderItem,keyExtractor, and theonConfigurePanGestureconfiguration call;- lifecycle and progress callbacks;
- ref calls,
onLayout, PaginationonPress, and accessibility labels.