react-native icon indicating copy to clipboard operation
react-native copied to clipboard

Fix onStartReached not called when list content is small

Open janicduplessis opened this issue 2 years ago • 1 comments

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.

janicduplessis avatar Feb 06 '24 21:02 janicduplessis

cc @NickGerleman

janicduplessis avatar Feb 06 '24 21:02 janicduplessis

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

facebook-github-bot avatar Feb 07 '24 14:02 facebook-github-bot

@cipolleschi merged this pull request in facebook/react-native@4dcc1d3efbd86a4ac42c801af3303e4dae4c0418.

facebook-github-bot avatar Feb 08 '24 04:02 facebook-github-bot