Props

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

PropTypeDefaultDescription
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

PropTypeDefaultDescription
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

PropTypeDefaultDescription
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:

<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

PropTypeDefaultDescription
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

PropTypeThreadDescription
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

PropTypeDescription
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;
}
  • 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

<Pagination count={items.length} progress={progress} />
PropTypeDefaultDescription
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, 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.