I'm creating a carousel component in React Native using a FlatList
and I use useState
hook to control the index of image, images load properly and the problem is I cant use my buttons to control the carousel. for example when I tap on right arrow first time doesn't work but when I tap again it goes to next image.
here's my code:
const { width: windowWidth, height: windowHeight } = Dimensions.get("window");
const slideList = Array.from({ length: 5 }).map((_, i) => {
return {
id: i.toString(),
image: `https://picsum.photos/1440/2842?random=${i}`,
};
});
const Carousel = () => {
const [current, setCurrent] = useState(0);
const length = slideList.length;
const flatListRef = useRef();
const renderItem = ({ item }) => {
const arr = Object.values( item );
return (
<View style={styles.imagesContainer}>
<Image style={styles.image} source={{ uri: item.image }} />
</View>
);
}
const goNextSlide = () => {
setCurrent(current < length -1 ? current + 1 : 0);
flatListRef.current.scrollToIndex({ index: current, animated: true });
};
const goPrevSlide = () => {
setCurrent(current <= length - 1 && current >= 0 ? current -1 : 0);
flatListRef.current.scrollToIndex({ index: current, animated: true });
};
console.log(current)
return (
<View style={styles.screen}>
<View style={styles.controls}>
<TouchableOpacity style={styles.controlleft} onPress={goPrevSlide}>
<CarouselLeftArrow style={styles.leftArrow} size={28} fill='black' />
</TouchableOpacity>
<TouchableOpacity style={styles.controlRight} onPress={goNextSlide}>
<CarouselRightArrow style={styles.rightArrow} size={28} fill='black' />
</TouchableOpacity>
</View>
<FlatList
data={slideList}
keyExtractor={item => item.id}
renderItem={renderItem}
horizontal={true}
showsHorizontalScrollIndicator={false}
pagingEnabled={true}
ref={flatListRef}
/>
</View>
)
}
const styles = StyleSheet.create({
imagesContainer: {
width: windowWidth,
height: 250
},
image: {
width: '100%',
height: '100%'
},
controls: {
backgroundColor: 'yellow',
flexDirection: 'row',
justifyContent: 'space-between',
position: 'absolute',
zIndex: 2,
width: '100%',
top: 100
},
controlLeft: {
},
controlRight: {
}
})
export default Carousel;
any help would be appreciated.
goPrevSlide
setCurrent(current <= length - 1 && current >= 0 ? current -1 : 0);
When current >= 0
is not correct because if current equals zero then you set -1 to current in this case. Replace statement like setCurrent(current ? current - 1 : length - 1);
Since updating state is an async action, you can not handle updated variable immediately, you need to use effect
hook in order to catch it.
useEffect(() => {
// fires every time when "current" is updated
flatListRef.current.scrollToIndex({ index: current, animated: true });
}, [current]);
Remove setCurrent
function from both handler