SudoPlz
SudoPlz

Reputation: 23173

Prepending data to a FlatList always shows the first child

this is our FlatList, say hello:

<FlatList
    data={this.state.dates}
...
/>

we feed it with the following dates:

this.state = {
    dates: [
        '21/06/2019',
        '22/06/2019',
        '23/06/2019',
    ]
};

then when the visible date changes (onViewableItemsChanged), if we end up to the first item (21/06/2019), we prepend data, so that the new state becomes:

dates: [
        '18/06/2019',
        '19/06/2019',
        '20/06/2019',
        '21/06/2019',
        '22/06/2019',
        '23/06/2019',
]

The Problem:

right after we prepend the data, instead of STILL seeing 21/06/2019 (which was the date when the prepend took place) we now see 19/06/2019.

That's because below the hood, 21/06/2019 used to be index 0, but after the prepend, index 0 corresponds to 19/06/2019.

What we want:

I'm trying to make it so that the day remains the same after prepending data.

Please don't tell me to use scrollToPosition because that's a hack really, not the solution. Is there any good solution to that problem?

Thank you

Upvotes: 15

Views: 8116

Answers (4)

kidroca
kidroca

Reputation: 3856

There's a library: https://github.com/GetStream/react-native-bidirectional-infinite-scroll that allows you to both preprend or append data and preserve scroll position

It's basically an extension over the FlatList and supports all the props available for a plain FlatList

From their example usage tutorial: https://dev.to/vishalnarkhede/react-native-how-to-build-bidirectional-infinite-scroll-32ph#%F0%9F%96%A5-tutorial-chat-ui-with-bidirectional-infinite-scroll

It looks like it would be enough to just prepend that data to the top exactly like you're trying to do

Upvotes: 1

clw8
clw8

Reputation: 11

Leaving this here, since it took me a while to get a working solution/ workaround to this problem that doesn't leave a bad taste in my mouth: prepopulate the array with empty data, and then use the scrollToIndex method.

this.state = {
  dates: [
    '',
    '',
    '',
    '21/06/2019',
    '22/06/2019',
    '23/06/2019',
  ]
};

And then:

<FlatList
    data={this.state.dates}
    ref={flatListRef}
    getItemLayout={(data, index) => (
      {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
    )}
...
/>

inside your componentDidMount:

const startingIndex = 4
flatListRef.current.scrollToIndex({index: startingIndex, animated: false, viewPosition: 0})

Upvotes: 1

Kasra
Kasra

Reputation: 2189

that maintainVisibleContentPosition does not work if you prepend data while you are at a scroll position of 0 (all the way to the top). It does work if you are prepending while not a the top. Even scroll Y of 1 would be enough.

check this

Unfortunately this still an issue even in React Native 0.63.3 and has not been solved.

Upvotes: 2

SiSa
SiSa

Reputation: 2684

There is an undocumented prop maintainVisibleContentPosition on ScrollView that do what you want, but unfortunately it's not working on android

I found another 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!

I've opened an issue on github also, but there is not any complete solution yet
Thanks to sgtpepper43 for undocumented iOS solution

Upvotes: 2

Related Questions