5

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?

Ryan Pergent
  • 4,432
  • 3
  • 36
  • 78
  • 1
    Check this: https://github.com/FaridSafi/react-native-gifted-chat/issues/1860#issuecomment-656115581 – SKarpov Nov 17 '20 at 13:42
  • fyi, onContentSizeChange is not reliable. it will stop getting updated after the size has increased to a certain number due to optimisations for large flat lists, and you'll end up with delta being 0. also, the change could be triggered multiple times during a single append. – Prasanth Nov 19 '20 at 14:08
  • @Prasanth yeah I had a lot of issues with onContentSizeChange, so I am definitely looking for an alternative. – Ryan Pergent Nov 20 '20 at 09:52
  • @SKarpov I already tried this solution. I end up with an extremely stiff scrolling (in comparison to the smooth scrolling you normally get). It's not really usable in a finished product, imo... – Ryan Pergent Nov 20 '20 at 09:55

1 Answers1

0

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>
);

}

Lord Pooria
  • 522
  • 6
  • 14
  • Unfortunately, `inverted` does not work well on web. The mouse wheel scrolling becomes inverted too (at least on chrome). Also, I would like to know how to prepend data in general, no matter if prepending means adding to the top (normal) or the bottom (inverted) of the screen. – Ryan Pergent Nov 13 '20 at 11:04