Prepend data to a FlatList on react native web, while maintaining visible content

Viewed 423

Is it possible to implement a Flatlist with react native web where you prepend data while maintaining the visible content?

Right now, it jumps to the top of the Flatlist when you prepend something. I am using onContentSizeChange to force move the scroll position after an update, but the experience is terrible as there is sometimes a huge delay before the update. Check this slack to see what I mean: https://snack.expo.io/@divone/prepend-data-to-flatlist-on-web

Was anyone successful in implementing a Chat-like Flatlist with React Native Web? If yes, how to achieve it?


EDIT: I discovered that on react native web, content visibility is automatically maintained when you prepend data IF AND ONLY IF the scroll bar is not at the top of the screen. (snack)

So my question still stands... how to prepend data and maintain visiblity even if the scrollbar is scrolled all the way up?

1 Answers

You could invert your flatlist and then also reverse your data perspective. I mean when you reverse the flatlist's direction you add data at the end of it and no jump happend then. I modify your shared code and paste it below to be clear what I said hope it helps:

import * as React from 'react';
import { Text, View, Button, FlatList } from 'react-native';

let lastContentHeight = 0;
let lastY = 0;

export default function App() {
const [data, setdata] = React.useState([]);

const flatlist = React.useRef();

const addData = React.useCallback(() => {
    const first =  data.length ? data[data.length-1].key : 1;
    const newArray = [];
    for (let i = first ; i <first+ 15; i++) {
        newArray.push({ key: i });
    }
    setdata([ ...data,...newArray]);
}, [data]);

React.useEffect(() => {
    addData();
}, []);

// const onContentSizeChange = (contentWidth, contentHeight) => {
//  const delta = contentHeight - lastContentHeight;
//  const newY = lastY + delta;
//  flatlist.current.scrollToOffset({ animated: false, offset: newY });
//  lastY = newY;
//  lastContentHeight = contentHeight;
// };

const onScroll = ({
    nativeEvent: {
        contentOffset: { y },
    },
}) => {
    lastY = y;
};

return (
    <View style={{ height: 600 }}>
        <Button onPress={addData} title="Prepend data" />
        <FlatList
  inverted
            ref={flatlist}
            data={data}
            renderItem={({ item }) => <Text style={{ padding: 80 }}>{item.key}</Text>}
            // onContentSizeChange={onContentSizeChange}
            onScroll={onScroll}
        />
    </View>
);

}

Related