React-native-snap-carousel: carouselRef .getPositionIndex is not a function

Created on 23 Nov 2019  路  9Comments  路  Source: meliorence/react-native-snap-carousel

Hi,

App is crashing with message 'carouselRef .getPositionIndex is not a function' when clicking on pagination dots

const CarouselPage = ({navigation, ...props}) => {
const [activePage, setActivePage] = useState(0);
useEffect( () => { console.log(' active page : ', activePage) }, [activePage] );

let carouselRef = useRef();
    return(
       <Carousel
          ref={(c) => {carouselRef = c}}
            sliderWidth={screenWidth}
            sliderHeight={screenWidth}
            itemWidth={screenWidth}
            data={entries}
            renderItem={_renderItem}
            onSnapToItem={(index) => { setActivePage(index) }}
        />

        <Pagination
          dotsLength={entries.length}
          activeDotIndex={activePage}
          containerStyle={{ backgroundColor: 'rgba(0, 0, 0.6, 0.5)' }}
          dotStyle={{
              width: 10,
              height: 10,
              borderRadius: 5,
              marginHorizontal: 8,
              backgroundColor: 'rgba(255, 255, 255, 0.92)'
          }}
          inactiveDotStyle={{
              // Define styles for inactive dots here
          }}
          inactiveDotOpacity={0.4}
          inactiveDotScale={0.6}
          tappableDots={true}
          tappableDots={ !!carouselRef }
          carouselRef={ carouselRef }
        />
    );
};

i am using RN: 0.61.4, react-native-snap-carousel: 3.8.4

can anyone help me in fixing this issue

Most helpful comment

@venkataluri here is a workaround for you

import React, { useState, useRef } from 'react';
import { Dimensions, Text, View, TouchableOpacity } from 'react-native';
import Carousel, { Pagination } from 'react-native-snap-carousel';

const { height, width } = Dimensions.get('window');

const data = [
    <View id={'1'} width={width} height={height} backgroundColor="orange">
        <Text style={{ fontSize: 32, color: 'red' }}>1</Text>
    </View>,
    <View id={'2'} width={width} height={height} backgroundColor="yellow">
        <Text style={{ fontSize: 32, color: 'red' }}>2</Text>
    </View>,
    <View id={'3'} width={width} height={height} backgroundColor="green">
        <Text style={{ fontSize: 32, color: 'red' }}>3</Text>
    </View>,
    <View id={'4'} width={width} height={height} backgroundColor="blue">
        <Text style={{ fontSize: 32, color: 'red' }}>4</Text>
    </View>,
    <View id={'5'} width={width} height={height} backgroundColor="indigo">
        <Text style={{ fontSize: 32, color: 'red' }}>5</Text>
    </View>,
    <View id={'6'} width={width} height={height} backgroundColor="violet">
        <Text style={{ fontSize: 32, color: 'red' }}>6</Text>
    </View>,
];

const CarouselPaginationBar = props => {
    return (
        <TouchableOpacity
            onPress={() => {
                props.carouselRef.current.snapToItem(props.index);
            }}
        >
            <View
                width={props.width}
                marginHorizontal={4}
                height={3}
                backgroundColor={
                    props.inactive ? 'rgba(0, 0, 0, 0.20)' : 'rgba(0, 0, 0, 0.90)'
                }
            ></View>
        </TouchableOpacity>
    );
};

const HomeScreen = ({ screenProps: { chooseMode, mode }, ...props }) => {
    const [activeSlide, setActiveSlide] = useState(0);
    const carouselRef = useRef(null);

    const getPagination = () => (
        <Pagination
            dotsLength={data.length}
            activeDotIndex={activeSlide}
            containerStyle={{
                backgroundColor: 'white',
                paddingVertical: 8,
            }}
            dotElement={
                <CarouselPaginationBar width={width / 9} carouselRef={carouselRef} />
            }
            inactiveDotElement={
                <CarouselPaginationBar
                    width={width / 9}
                    carouselRef={carouselRef}
                    inactive
                />
            }
        />
    );

    return (
        <View>
            {getPagination()}

            <View>
                <Carousel
                    ref={carouselRef}
                    data={data}
                    renderItem={item => item.item}
                    sliderWidth={width}
                    sliderHeight={height}
                    itemWidth={width}
                    activeSlideAlignment={'start'}
                    onSnapToItem={index => setActiveSlide(index)}
                />
            </View>
        </View>
    );
};

export default HomeScreen;

All 9 comments

Having the same issue

can any one help me to fix this issue

Same issue here

I haven't tried extensively yet to find the issue

You could get around it by calling the carousel's scrollToItem function ref in a custom dot component using the index provided by the dotElement and inactiveDotElement prop

this is my currently non working code that is having the same issue, not sure what I'm doing wrong I have it set up the most basic way

    const carouselRef = useRef(null);
              // Pagination component
            <Pagination
                dotsLength={data.length}
                activeDotIndex={activeSlide}
                carouselRef={carouselRef}
                tappableDots
                containerStyle={{
                    backgroundColor: 'white',
                    paddingVertical: 8,
                }}
                dotContainerStyle={{ marginHorizontal: 2 }}
                dotStyle={{
                    width: width / 8,
                    height: 4,
                    borderRadius: 0,
                }}
                inactiveDotStyle={{
                    width: width / 8,
                    height: 4,
                    borderRadius: 0,
                }}
                inactiveDotOpacity={0.4}
                inactiveDotScale={0.8}
            />
               // Carousel component
            <Carousel
                ref={carouselRef}
                data={data}
                renderItem={item => {
                return React.cloneElement(item.item, {
                        values,
                    handleBlur,
                    handleChange,
                         });
                }}
                sliderWidth={width}
                sliderHeight={height}
                itemWidth={width}
                activeSlideAlignment={'start'}
                onSnapToItem={index => setActiveSlide(index)}
                scrollInterpolator={scrollInterpolator}
                slideInterpolatedStyle={animatedStyles}
            />

@venkataluri here is a workaround for you

import React, { useState, useRef } from 'react';
import { Dimensions, Text, View, TouchableOpacity } from 'react-native';
import Carousel, { Pagination } from 'react-native-snap-carousel';

const { height, width } = Dimensions.get('window');

const data = [
    <View id={'1'} width={width} height={height} backgroundColor="orange">
        <Text style={{ fontSize: 32, color: 'red' }}>1</Text>
    </View>,
    <View id={'2'} width={width} height={height} backgroundColor="yellow">
        <Text style={{ fontSize: 32, color: 'red' }}>2</Text>
    </View>,
    <View id={'3'} width={width} height={height} backgroundColor="green">
        <Text style={{ fontSize: 32, color: 'red' }}>3</Text>
    </View>,
    <View id={'4'} width={width} height={height} backgroundColor="blue">
        <Text style={{ fontSize: 32, color: 'red' }}>4</Text>
    </View>,
    <View id={'5'} width={width} height={height} backgroundColor="indigo">
        <Text style={{ fontSize: 32, color: 'red' }}>5</Text>
    </View>,
    <View id={'6'} width={width} height={height} backgroundColor="violet">
        <Text style={{ fontSize: 32, color: 'red' }}>6</Text>
    </View>,
];

const CarouselPaginationBar = props => {
    return (
        <TouchableOpacity
            onPress={() => {
                props.carouselRef.current.snapToItem(props.index);
            }}
        >
            <View
                width={props.width}
                marginHorizontal={4}
                height={3}
                backgroundColor={
                    props.inactive ? 'rgba(0, 0, 0, 0.20)' : 'rgba(0, 0, 0, 0.90)'
                }
            ></View>
        </TouchableOpacity>
    );
};

const HomeScreen = ({ screenProps: { chooseMode, mode }, ...props }) => {
    const [activeSlide, setActiveSlide] = useState(0);
    const carouselRef = useRef(null);

    const getPagination = () => (
        <Pagination
            dotsLength={data.length}
            activeDotIndex={activeSlide}
            containerStyle={{
                backgroundColor: 'white',
                paddingVertical: 8,
            }}
            dotElement={
                <CarouselPaginationBar width={width / 9} carouselRef={carouselRef} />
            }
            inactiveDotElement={
                <CarouselPaginationBar
                    width={width / 9}
                    carouselRef={carouselRef}
                    inactive
                />
            }
        />
    );

    return (
        <View>
            {getPagination()}

            <View>
                <Carousel
                    ref={carouselRef}
                    data={data}
                    renderItem={item => item.item}
                    sliderWidth={width}
                    sliderHeight={height}
                    itemWidth={width}
                    activeSlideAlignment={'start'}
                    onSnapToItem={index => setActiveSlide(index)}
                />
            </View>
        </View>
    );
};

export default HomeScreen;

@TerrellLinnell your solution is perfectly working
Thanks you very much

This should probably stay open as it is still an issue when using the component as intended.

The problem is still relevant.

I am seeing the same issue as well.

Same issue here. You can get around it by setting your carouselRef to the following:

carouselRef={carouselRef.current}

This issue exists because the ref is accessed directly instead of accessing the current attribute. When a ref is passed to an element in render, a reference to the node becomes accessible at the current attribute of the ref.

I'll create a pull request as soon as I have some time.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ajonno picture ajonno  路  4Comments

sujitpk-perennial picture sujitpk-perennial  路  3Comments

akyker20 picture akyker20  路  3Comments

niloufarMakhzani picture niloufarMakhzani  路  4Comments

CarbonC picture CarbonC  路  4Comments