I'm trying to create a select year by scrolling something like this:
I need the scroll to go both ways till maybe 0 to 9999, obviously I can't store that much value in a single array for a <Flatlist>
so I improvised and made it such that after reaching the end it would scroll back to the top
and reset to whatever the previous last year was +10 and it gave me this:
imp part of the source code:
function setrange(from = 2000, to=2010){
let temp_arr = [{ key: 0, title: '' }];//so that the selected item always stays in middle
let k=1;
for (let i = from; i <= to; i++)
temp_arr.push({ key: k++, title: i})
temp_arr.push({ key: k , title: '' });//so that the selected item always stays in middle
setDATA(temp_arr);
}
const [DATA, setDATA] = useState(...);
<FlatList
onEndReached={() => { setrange(from=DATA[DATA.length-2]['title'],to=DATA[DATA.length-2]['title']+10); Scrollref.current.scrollToIndex({ animated: false, index: 0 });}}
data={DATA}
ref={Scrollref}
...
/>
the complete source code
so how do I make it seem like an infinite scroll without stopping or loosing scroll momentum in between?
(also please don't recommend an external library if possible)
You actually don't need to create your own implementation of lazy loading if you're only rendering plain texts with static height, since FlatList has already one built-in. You just need to play with it's props to make it perfect for your use case.
Creating an array with 10000 items of course costs you a bit of memory (it is actually lower than youd expect) but, it is up to you whether you want every bit of performance.
Here is a snack to test it: https://snack.expo.dev/@truetiem/date-picker
const ITEM_HEIGHT = 60;
const SEPERATOR_HEIGHT = 1;
<FlatList
data={Array(9999)
.fill('')
.map((_, index) => (index + 1).toString())}
renderItem={({ item }) => (
<View
style={{
height: ITEM_HEIGHT,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text style={{ fontWeight: 'bold' }}>{item}</Text>
</View>
)}
ItemSeparatorComponent={() => (
<View
style={{ height: SEPERATOR_HEIGHT, width: '100%', backgroundColor: '#ccc' }}
/>
)}
keyExtractor={(_, index) => index.toString()}
getItemLayout={(_, index) => ({
length: ITEM_HEIGHT,
offset: (ITEM_HEIGHT * index) + (SEPERATOR_HEIGHT * index),
index,
})}
initialScrollIndex={2019}
initialNumToRender={10}
windowSize={9}
showsVerticalScrollIndicator={false}
snapToInterval={ITEM_HEIGHT + SEPERATOR_HEIGHT}
snapToAlignment={"center"}
/>