Fix onStartReached not called when list content is small
Summary:
Currently if the virtualized list content is small onStartReached won't be called initially when the list is mounted. This is because when the content is small onEndReached will be called initially preventing onStartReached from being called. In _maybeCallOnEdgeReached calling onEndReached and onStartReached are in the same conditional so they cannot both be triggered at once. To improve the consistency of onStartReached we should call both onEndReached and onStartReached if needed.
Changelog:
[GENERAL] [FIXED] - Call onStartReached initially when list is small and onEndReached is called
Test Plan:
I used this code to test in RN Tester (replace content of RNTesterAppShared.js)
import React, { useState, useEffect } from "react";
import { StyleSheet, FlatList, View, Text, TouchableOpacity } from "react-native";
function App() {
const [data, setData] = useState(generatePosts(4));
const [idCount, setIdCount] = useState(1);
const renderItem = ({ item }) => <Item data={item} />;
const keyExtractor = (item) => item.id.toString();
console.log("-------")
return (
<View style={{ flex: 1, marginVertical: 20 }}>
<FlatList
key={idCount}
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
onEndReachedThreshold={0.05}
onEndReached={() => console.log("onEndReached")}
onStartReachedThreshold={0.05}
onStartReached={() => console.log("onStartReached")}
inverted
/>
<TouchableOpacity style={{height: 50, width: '100%', backgroundColor: 'purple'}} onPress={()=>{
setIdCount(state => state + 1)
setData(generatePosts(2))
}}><Text> Press</Text></TouchableOpacity>
</View>
);
}
function Item({ data }) {
return (
<View style={styles.item}>
<Text style={styles.title}>
{data.id} - {data.title}
</Text>
</View>
);
}
const styles = StyleSheet.create({
item: {
backgroundColor: "#f9c2ff",
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 24,
},
});
const generatePosts = (count, start = 0) => {
return Array.from({ length: count }, (_, i) => ({
title: `Title ${start + i + 1}`,
vote: 10,
id: start + i,
}));
};
export default App;
Before the change only onEndReached is called, after the change both onStartReached and onEndReached is called.
cc @NickGerleman
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.
@cipolleschi merged this pull request in facebook/react-native@4dcc1d3efbd86a4ac42c801af3303e4dae4c0418.