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
dataItem[]requiredRaw application data. All public indices refer to this array.
renderItemCarouselRenderItem<Item>requiredJS-thread renderer for each mounted slide.
keyExtractor(item, index) => stringStable identity used to preserve selection across data updates.
defaultIndexnumber0Mount-only initial raw-data index.
loopbooleanfalseEnables 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.
itemSizenumbercontainer main-axis sizePage distance used by snapping and progress. Must be positive.
renderWindowSizenumberall slidesMaximum mounted slides including the current slide. Must be a positive integer.
styleStyleProp<ViewStyle>{}Root viewport style and container dimensions.
contentContainerStyleStyleProp<ViewStyle>{}Inner content layer. opacity and transform are library-owned.
testIDstringApplied to the root viewport.
onLayout(event: LayoutChangeEvent) => voidRoot 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
scrollEnabledbooleantrueEnables 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.
overscrollEnabledbooleantrueEnables resisted overdrag and rebound when loop={false}.
animationCarouselAnimationtiming, 500msTransition config for gesture snapping, commands, and autoplay.
onConfigurePanGesture(gesture: CarouselPanGesture) => voidConfigures 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
autoplaybooleanfalseControlled autoplay switch.
autoplayIntervalnumber3000Idle 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
progressSharedValue<number>UIFractional logical index, written by Carousel every frame.
onProgressChange(progress: number) => voidJSPer-frame logical progress callback.
scrollOffsetValueSharedValue<number>UIAdvanced 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() => voidJS callback once when an accepted gesture, command, or autoplay transition starts.
onSnapToItem(index: number) => voidJS 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
countnumberrequiredNon-negative integer number of raw-data dots.
progressread-only SharedValue<number>requiredSame logical progress produced by Carousel.
orientation"horizontal" | "vertical""horizontal"Horizontal start-edge order or vertical top-to-bottom order.
containerStyleStyleProp<ViewStyle>Outer style; cannot override direction or flexDirection.
dotStylePaginationDotStyle10 × 10 gray dotBase dot style.
activeDotStylePaginationDotStyledark base-size dotActive style inheriting omitted base fields.
onPress(index: number) => voidMakes dots focusable buttons and receives a raw-data index.
getItemAccessibilityLabel(index, count) => stringSlide N of MOnly 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.