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

FlatList automatically scrolls after adding new items

Open SiSa68 opened this issue 5 years ago • 143 comments

FlatList automatically scrolls after change data and adds new data in the front or middle of the data list. It only works correctly when adds new item to the end of list I checked scroll offset and understand that FlatList scrolls to keep the latest content Y offset I mean when the content size changes, the latest Y offset now is not where the user was before! but FlatList scrolls to it

React Native version: react-native: 0.59.4 System: OS: Windows 7 CPU: (2) x64 Intel(R) Pentium(R) CPU G4400 @ 3.30GHz Memory: 310.09 MB / 3.87 GB Binaries: Yarn: 1.15.2 - C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: 6.9.0 - C:\Program Files\nodejs\npm.CMD IDEs: Android Studio: Version 3.2.0.0 AI-181.5540.7.32.5056338

Describe what you expected to happen:

It shouldn't scroll to new position when I add new items to list, and should keep latest position where user was

Example code:

<FlatList inverted style={{flex: 1}} data={this.data} keyExtractor={(item, index) => item.id} renderItem={this.renderItem} ref={ref => this.flatList = ref} />

Code that adds new items to list:

this.data = [ ...newItems, ...this.data ];

SiSa68 avatar Jun 12 '19 14:06 SiSa68

If you only need this fixed in ios, there's an undocumented prop maintainVisibleContentPosition on ScrollView that ought to do what you want. Unfortunately it doesn't work on android. I've been trying to solve this problem for the last two days in my own code and it's a freaking nightmare.

sgtpepper43 avatar Jun 20 '19 22:06 sgtpepper43

@sgtpepper43 Thank you for participate I need in both android and iOS. I find workaround by keep latest y offset with onScroll and also save content height before and after adding new items with onContentSizeChange and calculate the difference of content height, and set new y offset to the latest y offset + content height difference!

But its not a good way, because it has UX problem. Firstly it scrolls down and after that scrolls back to the latest position And it's not working when I want to load my list item from realm database

There should be a simpler way to do this and I don't understand why there is not?!

SiSa68 avatar Jun 22 '19 11:06 SiSa68

That's the same point I'm at 😩 I was going to try and fix it, but it's taken longer to try to get the Android code building and running in our app then writing the fix itself will take... I still haven't gotten it to compile. So I'm giving up on that.

sgtpepper43 avatar Jun 22 '19 19:06 sgtpepper43

fyi, I've asked the same thing here https://stackoverflow.com/questions/56707931/prepending-data-to-a-flatlist-always-shows-the-first-child/56837491#56837491

No actual fixes so far.

Leaving that here for future reference.

SudoPlz avatar Jul 01 '19 16:07 SudoPlz

having the same issue here on trying to prepend data to my datasource, i found "maintainVisibleContentPosition" but that only works for IOS, Android is not supported have you guys found any other solutions on this without manually scrollToIndex of course

winardis avatar Jul 18 '19 02:07 winardis

I was afraid that there is no straightforward way to achieve this, but at the moment after a couple of days of trying to implement this feature, it looks like RN is not an appropriate tool to implement chat apps.

kirillpisarev avatar Jul 22 '19 12:07 kirillpisarev

I can not believe that they are not support this feature at all!!! I found RecyclerListView It might solve this problem, But I didn't currently have the opportunity to test it If someone has an opportunity, please test and give the result to the React Native community!

SiSa68 avatar Jul 22 '19 15:07 SiSa68

That's an issue for me as well, would be nice to have this working with SectionList.

jmacioszek avatar Jul 31 '19 16:07 jmacioszek

Have same problem Guys (( maintainVisibleContentPosition not work on Android

AVert avatar Aug 14 '19 10:08 AVert

I created a ticket in Canny, please upvote, this has to get fixed soon https://react-native.canny.io/feature-requests/p/allow-prepending-new-items-to-flatlists-without-side-effects

SudoPlz avatar Aug 14 '19 16:08 SudoPlz

@sahrens Could you please triage this? This is a regression/bug, right? If so, any advice how to fix it? Thanks!

AVert avatar Aug 26 '19 21:08 AVert

i check this same way not work

I can not believe that they are not support this future at all!!! I found RecyclerListView It might solve this problem, But I didn't currently have the opportunity to test it If someone has an opportunity, please test and give the result to the React Native community!

AVert avatar Aug 28 '19 16:08 AVert

I can not believe that they are not support this future at all!!! I found RecyclerListView It might solve this problem, But I didn't currently have the opportunity to test it If someone has an opportunity, please test and give the result to the React Native community!

@naqvitalha can you change you component to mak it work as we need?

AVert avatar Aug 28 '19 16:08 AVert

I can not believe that they are not support this future at all!!! I found RecyclerListView It might solve this problem, But I didn't currently have the opportunity to test it If someone has an opportunity, please test and give the result to the React Native community!

I try this - no way

AVert avatar Aug 29 '19 13:08 AVert

@AVert Thanks for your try. If you fix it, let's talk how you use that instead of ScrollView and maintainVisibleContentPosition. I will try that too. Best wishes for you.

woody-riddle avatar Aug 30 '19 21:08 woody-riddle

Clarification: I'm creating a chat app which will append pages of messages as user scrolls up, and prepend newly received messages to the bottom.

My solution using an inverted flatlist was to not render newly received messages at the bottom, unless/until the user is scrolled to the bottom. Here's how I achieved that:

  1. Add following component state variables

    • isScrolledBottom: boolean
    • newMessageList[]
  2. define a threshold for deciding if we are scrolled to bottom of list myThreshold = 100 pixels

  3. Create a method for handling onBottomReached while scrolling onBottomReached() { if(newMessageList > 0){ - append them to my flatlist data source - remove them from my newMessageList in component state - scroll to bottom } }

  4. flatlist onScroll: if (crossed 100px threshold, in either direction)

    • if at bottom, then call onBottomReached()
    • set state.isScrolledToBottom = T/F
  5. New message received: if(at bottom){ append to flatlist data source } else{ append to newMessageList }

This gave me the best user experience, since maintainVisibleContentPosition does not work on android, so I did not use it at all.

dmkerfont avatar Oct 10 '19 15:10 dmkerfont

@dmkerfont I don't really get it, what problem does this solve? It looks like you're not "prepending" data, looks like you're only appending.

Isn't the issue only apparent when someone tries to prepend data (and thus get's scrolled on a wrong date?) Have I miss-understood something?

Thanks

SudoPlz avatar Oct 10 '19 19:10 SudoPlz

@SudoPlz With an inverted flatlist. The 'end' of the list is actually the top, thus scrolling up will continue to add older pages ( appending to the end ).

When a new message comes in, prepending it to the front of the list will cause the data shifting issue as the indexes are reset.

Instead of prepending every message that comes in, I'm checking if the user is at/near the bottom or if they are scrolled up a significant distance.

If at bottom, then prepend and scroll down. Else, build a queue of messages to prepend.

If user reaches bottom, through a manual scroll or pressing a button like a 'New Message' indicator, then simply prepend the queued messages.

I have no experience with native code so I have no desire to implement maintainVisibleContentPosition at this time, but this is a decent workaround.

dmkerfont avatar Oct 10 '19 20:10 dmkerfont

@dmkerfont interesting, is it too much to ask for some visual example? I've taken the time to replicate what you said with numbers below, does it look right?

Example:

Inverted flatlist

[3]
[2] <-- Index 2 / User sees 2
[1]
[0]

user manually scrolls to the bottom, then:

[3]
[2] 
[1]
[0]<-- Index 0 / User sees 0

New items [4][5][6] get prepended:

[3]
[2] 
[1]
[0]
[4]
[5]
[6]<-- Index 0 / User sees 6

so the user ends up seeing [6] now (which is now index 0) .

Then as an extra step the user get's scrolled to 0 again?

  • Isn't that a problem? Shouldn't the user see [4] instead? (index 2) ? since it's the next item after [0] ?
  • Also another question, does appending (adding items after [3]) work fine using an inverted list?

I appreciate your time, thanks.

SudoPlz avatar Oct 10 '19 20:10 SudoPlz

@SudoPlz

Isn't that a problem? Shouldn't the user see [4] instead? (index 2) ? since it's the next item after [0] ?

Shoot... You are right. If I'm scrolled up (and want my scroll position preserved), then I build my list of new messages. Once I scroll down manually, when I hit the bottom and the list [4][5][6] is prepended, I'm suddenly staring at item [6] instead of [4]. This means that the issue still exists, but you will only notice it if you are prepending more than 1 or 2 items to the list at a time while scrolling.

Perhaps this alternative isn't worth all the effort after all. :(

Also another question, does appending (adding items after [3]) work fine using an inverted list?

If you've done any paging, you will have noticed that adding items to the end of the list ( bottom for regular flatlist ) works as expected. This is the same when appending (top) to an inverted flatlist.

dmkerfont avatar Oct 10 '19 21:10 dmkerfont

Ok cool, please let me know if you find a way to make the user see [4] instead (the next item).

SudoPlz avatar Oct 10 '19 21:10 SudoPlz

What’s the story with this issue? Every time the data source on the flat list changes, say once new data is fetched or prended to the list it resets the scroll position. I’m building some sort of user feed, so I need to be able to update the data source without messing up the users scroll position.

Is this possible at all with react native? The maintainVisibleContentPosition prop seems to do nothing for me.

jesster2k10 avatar Nov 17 '19 21:11 jesster2k10

Edit: As Sisa68 noted, I misunderstood the struggle here. Mb

jakovB777 avatar Nov 25 '19 14:11 jakovB777

@jakovB777 I think our case are different from yours! We want to add item to both side of list, not only push on back. There is no problem when you have one side list with FlatList

SiSa68 avatar Nov 26 '19 08:11 SiSa68

Same problem =(( We add new items to the start of array and position is still 0

isuhar avatar Nov 26 '19 20:11 isuhar

This works for me:

Screen Shot 2019-12-06 at 9 44 51 AM

toddrimes avatar Dec 06 '19 17:12 toddrimes

anyone fix it?

meosieudang avatar Dec 24 '19 09:12 meosieudang

i use https://github.com/bolan9999/react-native-largelist and same issue.

Donhv avatar Dec 25 '19 12:12 Donhv

Is there a plan to fix this FlatList issue?

nahuelburgos avatar Jan 13 '20 15:01 nahuelburgos

I'm not familiar with the code base and relatively new to react-native but that being said, I think the problem is not the FlatList component itself, but the underlying ScrollView which has the exact same behavior:

push new items to bottom -> renders correct / doesn't move
push new items to the top -> it does all sorts of things but not what we want.

This is a really wild guess and I sadly could not test it at all because I could not get my self-compiled version of react-native to run without crashing, but maybe this is an issue: https://github.com/facebook/react-native/blob/0ee7fb98cc9cae89196570de306e37eefdd3b434/Libraries/Components/ScrollView/ScrollView.js#L726-L736 ?

At least it checks for content at the top and then sets the offset.

Again I'm just trying to help here but it may very well be that this is completely wrong and stupid.

Edit: I gave it some more thoughts and I am now in the opinion that this probably cannot be the issue. If you push content to the bottom there would have to be some algorithm that determines the new desired scroll offset which this certainly is not... But I still hope that someone looks at the ScrollView

Elias-Graf avatar Jan 16 '20 08:01 Elias-Graf