I am using a SectionList in React Native to display multiple sections with multiple items in each section. I am programmatically scrolling to specific sections and items using the scrollToLocation method.
The issue I am facing is that if I attempt to scroll to an item with an itemIndex of 0, the SectionList always scrolls to the first item of the first section, regardless of the sectionIndex I provide. If the itemIndex is greater than 0, the scrolling works as expected and goes to the correct section and item. The issue is happening in iOS. Here’s a simplified code to reproduce the issue:
import React, { useRef } from 'react';
import {
SectionList,
View,
Text,
Button,
StyleSheet,
StatusBar,
} from 'react-native';
const App = () => {
const sectionListRef = useRef<SectionList>(null);
const sections = Array.from({ length: 10 }, (_, sectionIndex) => ({
title: `Section ${sectionIndex + 1}`,
data: Array.from(
{ length: 30 },
(_, itemIndex) => `Item ${sectionIndex + 1}.${itemIndex + 1}`
),
}));
const scrollToLocation = ({
sectionIndex,
itemIndex,
}: {
sectionIndex: number;
itemIndex: number;
}) => {
{
sectionListRef.current?.scrollToLocation({
sectionIndex,
itemIndex,
viewPosition: 0.5, // Center the item in the view
});
}
};
const onScrollFail = (info: any) => {
console.log('Failed to scroll, retrying', info);
setTimeout(() => {
scrollToLocation({ sectionIndex: 0, itemIndex: info.index });
}, 500);
};
return (
<View style={styles.container}>
<View style={styles.buttonsContainer}>
<Button
title="Sec: 1 item: 1"
onPress={() => scrollToLocation({ sectionIndex: 0, itemIndex: 0 })}
/>
<Button
title="Sec: 4 item: 1"
onPress={() => scrollToLocation({ sectionIndex: 3, itemIndex: 0 })}
/>
</View>
<SectionList
ref={sectionListRef}
sections={sections}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item}</Text>
</View>
)}
renderSectionHeader={({ section }) => (
<View style={styles.header}>
<Text style={styles.headerText}>{section.title}</Text>
</View>
)}
onScrollToIndexFailed={onScrollFail}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 10,
paddingTop: 50,
},
buttonsContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 10,
},
item: {
padding: 15,
backgroundColor: '#f9f9f9',
borderBottomWidth: 1,
borderBottomColor: '#ddd',
},
header: {
padding: 10,
backgroundColor: '#e0e0e0',
},
headerText: {
fontWeight: 'bold',
},
});
export default App;
It could be tested in expo-snack as well.