Documents
Programmatic Control
Programmatic Control
Type
Document
Status
Published
Created
Apr 22, 2026
Updated
Apr 22, 2026

Programmatic Control#

import { Callout } from 'nextra/components'


Learn how to control the carousel programmatically using imperative methods via refs.

**Note:** This library doesn't support React-style controlled components (with an `index` prop). Instead, it uses an imperative API via refs for programmatic control.

Overview#

The carousel provides several methods to control its behavior programmatically:

  • scrollTo - Scroll to a specific index or relative position
  • next - Move to the next item(s)
  • prev - Move to the previous item(s)
  • getCurrentIndex - Get the current active index

Basic Setup#

First, create a ref and attach it to the carousel:

import React, { useRef } from 'react';
import Carousel, { ICarouselInstance } from 'react-native-reanimated-carousel';

function MyCarousel() {
  const carouselRef = useRef<ICarouselInstance>(null);

  return (
    <Carousel
      ref={carouselRef}
      // ... other props
    />
  );
}

Methods#

scrollTo#

The most versatile method for controlling carousel navigation.

Scroll to specific index#

// Jump to index 3 with animation
carouselRef.current?.scrollTo({ 
  index: 3, 
  animated: true 
});

// Jump to index 0 without animation
carouselRef.current?.scrollTo({ 
  index: 0, 
  animated: false 
});

Scroll relative to current position#

// Move 2 items forward (equivalent to calling next twice)
carouselRef.current?.scrollTo({ 
  count: 2, 
  animated: true 
});

// Move 1 item backward (equivalent to calling prev once)
carouselRef.current?.scrollTo({ 
  count: -1, 
  animated: true 
});

With callback#

carouselRef.current?.scrollTo({
  index: 2,
  animated: true,
  onFinished: () => {
    console.log('Scroll completed!');
  }
});

next & prev#

Simplified methods for moving forward or backward:

// Move to next item
carouselRef.current?.next({ animated: true });

// Move 3 items forward
carouselRef.current?.next({ 
  count: 3, 
  animated: true 
});

// Move to previous item
carouselRef.current?.prev({ animated: true });

// Move 2 items backward
carouselRef.current?.prev({ 
  count: 2, 
  animated: false 
});

getCurrentIndex#

Get the current active index:

const currentIndex = carouselRef.current?.getCurrentIndex();
console.log('Current index:', currentIndex);

Practical Examples#

Pagination Control#

import React, { useRef } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import { useSharedValue } from 'react-native-reanimated';
import Carousel, { ICarouselInstance, Pagination } from 'react-native-reanimated-carousel';

function CarouselWithPagination() {
  const carouselRef = useRef<ICarouselInstance>(null);
  const progress = useSharedValue<number>(0);
  const data = [...new Array(5).keys()];

  const onPressPagination = (index: number) => {
    carouselRef.current?.scrollTo({
      count: index - progress.value,
      animated: true,
    });
  };

  return (
    <View>
      <Carousel
        ref={carouselRef}
        data={data}
        onProgressChange={progress}
        // ... other props
      />

      <Pagination.Basic
        progress={progress}
        data={data}
        onPress={onPressPagination}
      />
    </View>
  );
}
function CarouselWithButtons() {
  const carouselRef = useRef<ICarouselInstance>(null);

  return (
    <View>
      <Carousel
        ref={carouselRef}
        // ... props
      />

      <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
        <TouchableOpacity 
          onPress={() => carouselRef.current?.prev({ animated: true })}
          <Text>Previous</Text>
        </TouchableOpacity>

        <TouchableOpacity 
          onPress={() => carouselRef.current?.next({ animated: true })}
          <Text>Next</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
}

Dynamic Content Updates#

When updating data and needing to scroll to new items:

function DynamicCarousel() {
  const carouselRef = useRef<ICarouselInstance>(null);
  const [items, setItems] = useState(initialItems);

  const addItemAndNavigate = (newItem) => {
    const newItems = [...items, newItem];
    setItems(newItems);

    // Wait for next render cycle before scrolling
    setTimeout(() => {
      carouselRef.current?.scrollTo({
        index: newItems.length - 1,
        animated: true
      });
    }, 0);
  };

  // Alternative: Use useEffect to handle timing
  useEffect(() => {
    if (items.length > initialItems.length) {
      // Scroll to the last item when new items are added
      carouselRef.current?.scrollTo({
        index: items.length - 1,
        animated: true
      });
    }
  }, [items]);

  return (
    <Carousel
      ref={carouselRef}
      data={items}
      // ... other props
    />
  );
}

Common Patterns#

function AutoAdvanceCarousel() {
  const carouselRef = useRef<ICarouselInstance>(null);
  const [currentIndex, setCurrentIndex] = useState(0);
  const data = [...new Array(5).keys()];

  useEffect(() => {
    const timer = setInterval(() => {
      const nextIndex = (currentIndex + 1) % data.length;
      carouselRef.current?.scrollTo({
        index: nextIndex,
        animated: true
      });
      setCurrentIndex(nextIndex);
    }, 3000);

    return () => clearInterval(timer);
  }, [currentIndex, data.length]);

  return (
    <Carousel
      ref={carouselRef}
      data={data}
      // ... other props
    />
  );
}

Jump to Item by ID#

function SearchableCarousel() {
  const carouselRef = useRef<ICarouselInstance>(null);
  const data = [
    { id: 'item1', title: 'Item 1' },
    { id: 'item2', title: 'Item 2' },
    { id: 'item3', title: 'Item 3' },
  ];

  const jumpToItemById = (itemId: string) => {
    const index = data.findIndex(item => item.id === itemId);
    if (index !== -1) {
      carouselRef.current?.scrollTo({
        index,
        animated: true
      });
    }
  };

  return (
    <View>
      <Carousel
        ref={carouselRef}
        data={data}
        // ... other props
      />

      <TouchableOpacity onPress={() => jumpToItemById('item2')}>
        <Text>Jump to Item 2</Text>
      </TouchableOpacity>
    </View>
  );
}

Important Notes#

**Race Condition Warning:** When updating data and immediately calling scroll methods, you might encounter race conditions. The carousel may not have rendered the new data yet. Use `setTimeout` or `useEffect` to ensure proper timing. **No Controlled Component Pattern:** Unlike typical React components, this carousel doesn't support controlled mode via props (like `currentIndex={index}`). All programmatic control must be done through the imperative ref API.

API Reference#

scrollTo Options#

PropertyTypeDefaultDescription
indexnumber-Target index to scroll to
countnumber-Relative position change (positive = forward, negative = backward)
animatedbooleantrueWhether to animate the scroll
onFinished() => void-Callback when scroll completes

next/prev Options#

PropertyTypeDefaultDescription
countnumber1Number of items to advance
animatedbooleantrueWhether to animate the scroll
onFinished() => void-Callback when scroll completes

This imperative approach gives you full control over the carousel's navigation while maintaining smooth animations and proper state management.

Programmatic Control | Dosu