react-native-reanimated-carousel

repository·main·Indexed 25 days ago

https://github.com/dohooo/react-native-reanimated-carousel

A performant and highly customizable carousel component for React Native, powered by Reanimated and Gesture Handler. It supports various layouts including parallax and stack, custom animations, autoplay, and pagination. Version 5.0.0 requires React Native 0.80+, Reanimated 4.1.0+, and Gesture Handler >=2.9.0 <3.0.0.

Tokens
34.5K
Snippets
67
Records
156
Agent score
85%

What's inside react-native-reanimated-carousel

  1. Understand thread boundaries in react-native-reanimated-carousel

    main

    The library splits operations between the UI thread (Worklets) and the JS thread to ensure smooth animations. Understanding this boundary is important for performance and debugging.

    UI thread / Worklets handle:

    • Animation properties: handlerOffset, progress, relativeProgress.
    • Motion, visible ranges, layout transforms, and item animations.
    • Gesture handlers and consumer gesture observers.
    • Pagination interpolation.

    JS thread handles:

    • React rendering, renderItem, and keyExtractor.
    • Configuration calls for onConfigurePanGesture.
    • Refs and public lifecycle/progress callbacks.
    • Layout events (onLayout), pagination presses, and accessibility label factories.

    Cross-thread communication is managed explicitly using scheduleOnRN or scheduleOnUI.

  2. Compare react-native-reanimated-carousel with react-native-snap-carousel

    main

    When choosing between carousel libraries for React Native, consider the following performance characteristics:

    • react-native-snap-carousel: May experience issues with infinite scrolling when swiping quickly (getting stuck or waiting for the next element to appear). It is better suited for scenarios where you want to see the content clearly at the junction points during a swipe.
    • react-native-reanimated-carousel: Designed for high performance using a different architectural approach. It is specifically optimized to handle fast swiping (e.g., ten slides per second) without the stuttering or sticking issues common in other libraries.
  3. Set up programmatic control with CarouselRef

    main

    The Carousel component is uncontrolled. To navigate or control the carousel after mounting, use the defaultIndex prop for the initial position and a CarouselRef to access imperative methods. Use React.useRef<CarouselRef>(null) to create the ref.

    import * as React from "react";
    import {
      Carousel,
      type CarouselRef,
    } from "react-native-reanimated-carousel";
    
    function ProductCarousel() {
      const ref = React.useRef<CarouselRef>(null);
    
      return (
        <Carousel
          ref={ref}
          data={products}
          keyExtractor={(product) => product.id}
          renderItem={({ item }) => <ProductCard product={item} />}
        />
      );
    }
  4. Migrate from v3.x to v4.x

    main

    To upgrade react-native-reanimated-carousel from version 3.x to 4.x, follow these steps:

    1. Update Dependencies: Ensure your project meets the following minimum requirements:
      • react: >=18.0.0
      • react-native: >=0.70.3
      • react-native-gesture-handler: >=2.9.0
      • react-native-reanimated: >=3.0.0
    2. Update Gesture Handling: Replace panGestureHandlerProps with onConfigurePanGesture using a worklet.
    3. Update Event Handlers: Rename onScrollBegin to onScrollStart.
    4. Update Animations: Update customAnimation functions to accept the index as a second parameter.
    5. Update Event Handler Worklets: Ensure gesture callbacks include the 'worklet'; directive.
    6. Handle defaultIndex Changes: Note that defaultIndex is now only used for the initial value. To change the index after mounting, use the carousel ref and .scrollTo({ index: newIndex, animated: true }).
  5. Migrate Carousel layout and mode configuration

    main

    In v5, the mode and modeConfig props are replaced by a single layout prop. This is a manual migration step.

    Example conversion:

    From v4:

    <Carousel
      mode="parallax"
      modeConfig={{
        parallaxScrollingOffset: 100,
        parallaxScrollingScale: 0.8,
        parallaxAdjacentItemScale: 0.64,
      }}
    />

    To v5:

    <Carousel
      layout={{
        type: "parallax",
        offset: 100,
        scale: 0.8,
        adjacentScale: 0.64,
      }}
    />

    Layout field mappings:

    v4 fieldv5 field
    showLengthvisibleCount
    moveSizeexitDistance
    stackIntervalspacing
    scaleIntervalscaleStep
    opacityIntervalopacityStep
    rotateZDegrotation
    snapDirectionexitDirection

    Note: layout and itemAnimation are mutually exclusive.

  6. Handle RTL (Right-to-Left) layouts

    main

    Horizontal RTL is detected via I18nManager.isRTL.

    • Data Order: Keep data in logical order. next(), autoplayDirection="forward", progress, and signed offset retain their standard meanings.
    • Gestures: A physical right swipe advances the carousel in RTL.
    • Animations: Custom itemAnimation callbacks receive logical progress. If you use direction-sensitive translateX values, you must mirror them manually in your application to account for RTL.
  7. Configure Autoplay behavior

    main

    Autoplay is a controlled scheduler that triggers after the previous movement has settled.

    Key Behaviors:

    • Interval: The autoplayInterval is measured from the moment the previous movement settles, not from the start of the animation.
    • Pausing: Autoplay automatically pauses during user interaction or any in-flight transition.
    • Looping: With loop={false}, a rejected boundary command (trying to go past the end) will end the autoplay chain.
    • Interaction: Setting scrollEnabled={false} affects pan input but does not stop autoplay or commands.
  8. Nest Carousel in `ScrollView` or `FlatList`

    main

    When nesting a horizontal Carousel inside a vertical ScrollView or FlatList, the carousel might suppress the parent's scroll gestures. To prevent small horizontal movements from capturing the parent scroll, use the onConfigurePanGesture prop to configure the pan gesture's activeOffsetX using react-native-gesture-handler.

    <Carousel
      {...}
      onConfigurePanGesture={(gesture) => {
        gesture.activeOffsetX([-10, 10]);
      }}
    />
  9. Handle data updates and selection

    main

    When updating the data prop, use keyExtractor to ensure the current item survives insertions or reordering. If the selected key exists, it remains selected. If the key disappears or no keyExtractor is provided, the old numeric index is clamped to the new range.

    To select a newly added item, navigate using scrollTo inside a useEffect after the data update has been committed to React.

    const [pendingIndex, setPendingIndex] = React.useState<number | null>(null);
    
    function addProduct(product: Product) {
      setProducts((current) => {
        setPendingIndex(current.length);
        return [...current, product];
      });
    }
    
    React.useEffect(() => {
      if (pendingIndex === null || pendingIndex >= products.length) return;
      ref.current?.scrollTo({ index: pendingIndex });
      setPendingIndex(null);
    }, [pendingIndex, products.length]);