Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flatlist onEndReached gets called multiple times when the height of the ListFooterComponent changes #48273

Open
KristineTrona opened this issue Dec 14, 2024 · 0 comments

Comments

@KristineTrona
Copy link

KristineTrona commented Dec 14, 2024

Description

FlatList can enter a state where onEndReached gets called in a loop if I use the onEndReached prop to fetch the next page of the data and this causes a change in the height of ListFooterComponent (see attached screen recording).

Adding a fixed footer height in ListFooterComponentStyle to the component fixes the issue, however this isn't optimal as we would like to display different types of content depending on the state of the data.

Example code:
import {useCallback, useState} from 'react';
import {
  FlatList,
  StyleSheet,
  Text,
  View,
  ActivityIndicator,
} from 'react-native';

const ListFooter = ({isLoading}: {isLoading: boolean}) => {
  if (isLoading) {
    return (
      <View style={styles.loadingContainer}>
        <ActivityIndicator />
      </View>
    );
  }

  return (
    <View style={styles.endReachedContainer}>
      <Text>End reached</Text>
    </View>
  );
};

const App = () => {
  const [loading, setLoading] = useState(false);

  const fetchData = async () => {
    try {
      setLoading(true);
      await new Promise<void>(resolve => {
        setTimeout(() => {
          resolve();
        }, 1000);
      });
    } finally {
      setLoading(false);
    }
  };

  const onEndReached = async () => {
    console.log('CALLING ON END REACHED');

    await fetchData();
  };

  const renderItem = useCallback(({item}: {item: number}) => {
    return (
      <View style={styles.listItemContainer}>
        <Text>{item}</Text>
      </View>
    );
  }, []);

  return (
    <FlatList
      data={Array.from({length: 10}).map((_, index) => index)}
      renderItem={renderItem}
      onEndReached={onEndReached}
      onEndReachedThreshold={1}
      ListFooterComponent={<ListFooter isLoading={loading} />}
      // Adding this prop fixes it:
      // ListFooterComponentStyle={{height: 600}}
    />
  );
};

const styles = StyleSheet.create({
  listItemContainer: {
    height: 300,
    borderColor: 'black',
    borderWidth: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  loadingContainer: {
    height: 200,
    backgroundColor: 'pink',
    alignItems: 'center',
    justifyContent: 'center',
  },
  endReachedContainer: {
    height: 600,
    backgroundColor: 'orange',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

export default App;

Steps to reproduce

  1. Clone the repo with reproducer code
  2. Run the app on either iOS or Android (bug seems to be worse on Android)
  3. Scroll to the bottom of the list - you should notice the footer changing multiple times between loading and finished state. You will also notice multiple logs being fired from the onEndReached function as it gets called again and again.

React Native Version

0.76.5

Affected Platforms

Runtime - Android, Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 14.4.1
  CPU: (8) arm64 Apple M1 Pro
  Memory: 291.98 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.14.0
    path: ~/.nvm/versions/node/v20.14.0/bin/node
  Yarn:
    version: 1.22.22
    path: ~/.nvm/versions/node/v20.14.0/bin/yarn
  npm:
    version: 10.7.0
    path: ~/.nvm/versions/node/v20.14.0/bin/npm
  Watchman:
    version: 2024.10.21.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /Users/kristine/.rvm/gems/ruby-2.7.6/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.5
      - iOS 17.5
      - macOS 14.5
      - tvOS 17.5
      - visionOS 1.2
      - watchOS 10.5
  Android SDK:
    Android NDK: 26.2.11394342
IDEs:
  Android Studio: 2024.2 AI-242.23339.11.2421.12550806
  Xcode:
    version: 15.4/15F31d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 21.0.2
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 15.0.1
    wanted: 15.0.1
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.76.5
    wanted: 0.76.5
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

Stacktrace or Logs

-

Reproducer

https://github.com/KristineTrona/flatlist-onEndReached-called-in-loop

Screenshots and Videos

Bug:
Screen.Recording.2024-12-13.at.17.16.39.mov
With fixed height:
Screen.Recording.2024-12-13.at.17.32.33.mov
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants