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

React Native onEndReached FlatList trigger error

Open Pietro-Putelli opened this issue 1 year ago • 15 comments

Description

I'm developing a react native app using the version 0.71.3 and I'm having some problems with the extremely discussed onEndReached callback.

React Native Version

0.71.3

Output of npx react-native info

System: OS: macOS 12.6.3 CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz Memory: 228.86 MB / 8.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 18.14.0 - /usr/local/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 9.5.0 - /usr/local/bin/npm Watchman: Not Found Managers: CocoaPods: 1.12.0 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: Not Found IDEs: Android Studio: 2021.3 AI-213.7172.25.2113.9123335 Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: 17.0.2 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.2.0 => 18.2.0 react-native: 0.71.3 => 0.71.3 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

Here's my onEndReached re-implementation to prevent the callback to be triggered even if the list is empty and to trigger it only once:

if (!endReached.current && dataSize > 0) {
  endReached.current = true;
  onEndReached?.();
}

And every time the data size changes, the endReached is set to false again:

useEffect(() => {
  endReached.current = false;
}, [dataSize]);

And then the list:

<FlatList onEndReachedThreshold={0.2} />

Now the problem arise when loading the list for the first time, the onEndReached callback is triggered even if the list is empty and once the list is populated, downloading items asynchronously, and reach the end the callback it's not triggered.

But if the list data area cached, the second time I load the list the onEndReached is not triggered at the beginning but on the right way.

It seems that the error, or I think the bug, arise when the list is empty because data are loading, indeed if I set a condition to render the list only after the data are fully loaded, the onEndReached is trigged correctly.

Pietro-Putelli avatar Mar 19 '23 15:03 Pietro-Putelli

:warning: Newer Version of React Native is Available!
:information_source: You are on a supported minor version, but it looks like there's a newer patch available. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.

github-actions[bot] avatar Mar 19 '23 15:03 github-actions[bot]

I'm using:

  • React Native: 0.71.4
  • React: 18.2.0

and experiencing the same issue:

  • onEndReached triggers early before having any data.
  • when the data is loaded and reaches its first onEndReachedThreshold the onEndReached doesn't trigger.

As a workaround:

  • I have added a loadMore function to trigger when the page === 1 page === 1 ? this.handleLoadMore() : null;

Garamani avatar Mar 25 '23 07:03 Garamani

+1 on this issue, onEndReached isn't triggering on android, but works fine on iOS. No matter what threshold I set, it just doesn't trigger the onEndReached callback

  • React: 18.2.0
  • React Native: 0.71.8

ram95krishh avatar Jun 14 '23 15:06 ram95krishh

+1 on this issue too. It seems onEndReached triggers when the screen gets initially loaded but doesn't trigger when the end of screen is reached

React: 18.2.0 React Native: 0.71.8

slrent avatar Aug 28 '23 13:08 slrent

+1 on this error.

  • react: 18.2.0
  • react-native: 0.72.4

wangjh7 avatar Sep 20 '23 11:09 wangjh7

+1 on this too

  • react: 18.2.0
  • react-native: 0.72.5

troberts-28 avatar Oct 05 '23 14:10 troberts-28

  • 1 alguem com alguma soluçao?

ebenezer710 avatar Nov 06 '23 16:11 ebenezer710

Your problem most likely occurs in the onEndReach call when the asynchronous data has not yet been loaded. I recommend using something that prevents the list from being rendered before the data that will make it up arrives. For example: {this.state.data.length > 0 && ( <FlatList...

With that you will solve the problem of the first empty call of onEndReach and it will start working fine

iwakawamarcos avatar Nov 16 '23 12:11 iwakawamarcos

i solved by adding the { } to the const [data, setData] = useState( [ { } ] ); the Data is what is been rendered on the FlatList.

<FlatList
	ref={flatListRef}
	data={data}
	keyExtractor={(item) => item.IdProduto.toString()}
	renderItem={({ item }) => (
        )}
	onScroll={handleScroll}
	onEndReachedThreshold={0.9}
	onEndReached={() => {
		if (!loading && hasMore) {
			fetchData(subgroup || group || null, page, searchText, geral);
		}
	}}
	refreshControl={<RefreshControl refreshing={refreshing} />}
/>

ebenezer710 avatar Nov 16 '23 13:11 ebenezer710

Or try using Flash-List from Shopfy it is 1000% faster.

ebenezer710 avatar Nov 20 '23 14:11 ebenezer710

For those having this issue, here is my solution, I essentially switch the key on the FlatList, causing it to "re-mount" when data is loaded. This is probably not "great" for performance, but once the flatlist has data, nothing should be changing.

interface IUseOnEndReachedFix<Data> {
  data: Data[];
  key?: string;
  onEndReachedThreshold?: number;
  onEndReached?: () => any;
}
const useOnEndReachedFix = <Data, >({
  data,
  key = "default",
  onEndReachedThreshold,
  onEndReached,
}: IUseOnEndReachedFix<Data>) => ({
  // Aryk: I was having an issue where sometimes on the initial render of the FlatList, the data would load but
  // onEndReached would not trigger when you get to the end of the list. Lada reported this on the Messages
  // screen, but I've also noticed other folks having issues with this as well.
  // https://github.com/facebook/react-native/issues/36529#issuecomment-1814359203
  key: data?.length ? key : "onEndReachedFix",
  // When you have an empty array (like the initial state of "items"), it's calling onEndReached. 🤦
  //  https://github.com/facebook/react-native/pull/39574
  onEndReached: data?.length ? onEndReached : null,
  onEndReachedThreshold
});

Aryk avatar Dec 06 '23 21:12 Aryk

+1

No solutions yet?

emanusantos avatar Jan 12 '24 20:01 emanusantos

Or try using Flash-List from Shopify it is 1000% faster.

Wow, this solved it for me. General performance increase too and works with Expo. Took 2 mins to replace FlatList.

dan-pugsley avatar Jul 04 '24 14:07 dan-pugsley