Irfan
Irfan

Reputation: 97

How to create flatlist auto scroll with Hooks in React Native

I'm trying to create an auto scroll flatlist carousel that can also allow the user to scroll manually. The problem is that I get this error flatListRef.scrollToIndex is not a function. I tried searching how other people create an auto scroll flatlist but their solution is using class.

const flatListRef = useRef(null)
useEffect (() => { 
    const totalIndex = data.length - 1;
    setInterval (() => {
        if(flatListRef.current.index < totalIndex) {
            flatListRef.scrollToIndex({animated: true, index: flatListRef.current.index + 1})
        } else {
            flatListRef.scrollToIndex({animated: true, index: 0})
        }
    }, 3000)
}, []);

const renderItem = ({item}) => {
    return (
        <View style={styles.cardView}>
            <Image style={styles.image} source={item.image} resizeMode="contain"/>
        </View>
    )
} 
return (
    <View style={{paddingHorizontal: 10}} >
        <FlatList 
            ref={flatListRef}
            data={data} 
            keyExtractor={data => data.id}
            horizontal
            pagingEnabled
            scrollEnabled
            snapToAlignment="center"
            scrollEventThrottle={16}
            decelerationRate={"fast"}
            showsHorizontalScrollIndicator={true}
            persistentScrollbar={true}
            renderItem={renderItem}
        /> 
    </View>
);

styles:

cardView: {
    flex: 1, 
    width: width - 20,  
    height: height * 0.21,
    backgroundColor: Colors.empty,
    alignItems: 'center',
    justifyContent: 'center', 
},
image: {
    backgroundColor: Colors.empty,
    width: width - 20,  
    height: height * 0.21,
}, 

Upvotes: 1

Views: 3700

Answers (3)

Fravel
Fravel

Reputation: 187

Just use scrollToEnd() method in useEffect with a useRef on the Flatlist.

Example :

  const flatListRef = useRef(null);
  const data = ['Message 1', 'Message 2', 'Message 3']; // Dummies datas

  useEffect(() => {
    // Scroll to the bottom when data change
    flatListRef.current.scrollToEnd({ animated: true });
  }, [data]);

  return (
    <View style={{ flex: 1 }}>
      <FlatList
        ref={flatListRef}
        data={data}
        renderItem={renderItem}
        keyExtractor={(item, index) => index.toString()}
        onContentSizeChange={() => flatListRef.current.scrollToEnd({ animated: true })}
      />
    </View>
  );
};

Upvotes: 0

Bhavin Parghi
Bhavin Parghi

Reputation: 176

as per the guide on React Native onScrollToIndexFailed
you have to override

onScroll={(e) => {
            this.setState({ currentIndex: Math.floor(e.nativeEvent.contentOffset.x / (dimensions.wp(this.props.widthPercent || 100) - 1)) });
          }}
onScrollToIndexFailed={info => {
            const wait = new Promise(resolve => setTimeout(resolve, 500));
            wait.then(() => {
flatListRef?.current?.scrollToIndex({ index: 0, animated: true });
            });
          }}

Upvotes: 0

Vin Xi
Vin Xi

Reputation: 1307

useRef returns a mutable object whose .current property is initialized to initial value. So basically you need to access scrollIndex like this

flatListRef.current.scrollToIndex({animated: true, index: flatListRef.current.index + 1})

Edit: To answer your comment, you should've asked directly for auto-scrolling, however, The code below should work!

const flatListRef = useRef(null)
let index=0;
const totalIndex = datas.length - 1;

  useEffect (() => { 
  setInterval (() => {
  index++;
  if(index < totalIndex) {
      flatListRef.current.scrollToIndex({animated: true, index: index})
  } else {
      flatListRef.current.scrollToIndex({animated: true, index: 0})
  }
  }, 1000)
  }, []);

Upvotes: 2

Related Questions