GetStream / react-native-bidirectional-infinite-scroll

📜 React Native - Bidirectional Infinite Smooth Scroll
https://getstream.github.io/react-native-bidirectional-infinite-scroll/
MIT License
236 stars 27 forks source link

inconsistencies #6

Open jcharbo opened 3 years ago

jcharbo commented 3 years ago

Hi, thanks for the work on this. I would like to use it but I'm finding that the results are so inconsistent that it's not usable in production. Your example works perfectly with an initial load of 50 and subsequent fetches of 10. If, however, I change all of the fetches to 30 then it starts bouncing around. I would just use 50/30 in my app yet I find that every change to the number of items or sizing of items causing the list to jump around while scrolling which makes it feel like a guessing game. Any advice? thanks

vishalnarkhede commented 3 years ago

@jcharbo you are absolutely correct. Its just a limitation of prop maintainVisibleContentPosition on react-native (and flat-list-mvcp). You will have to be careful around how many items you load while paginating.

jcharbo commented 3 years ago

@vishalnarkhede do you have any tips? Is there any logic to the behavior?

vishalnarkhede commented 3 years ago

@jcharbo sure!! Can you confirm if you have this issue only on Android? Or is it on iOS as well?

vishalnarkhede commented 3 years ago

@jcharbo basically maintaining scroll position logic, depends on virtualization on FlatList.

But if "X" has disappeared from the list after update (because of virtualization), then above logic doesn't work - which results in jank.

Fortunately FlatList lets us set windowSize to control virtualization. Its default value is 21. So you should try tuning this windowSize, which works best for your application - https://reactnative.dev/docs/virtualizedlist#windowsize

P.S I am talking mostly about flat-list-mvcp package here, which is for Android. For iOS, react-native handles it OOTB more gracefully.

Please let me know if that helps. Hopefully that should solve the issue, but if it doesn't, I can get back in the mud to look for more options :)

jcharbo commented 3 years ago

@vishalnarkhede I'm talking about ios. I haven't even started testing android.

vishalnarkhede commented 3 years ago

@jcharbo could you please share your code?

vishalnarkhede commented 3 years ago

For some reason I am not able reproduce this in example.

jcharbo commented 3 years ago

@vishalnarkhede It's as simple as changing both the initial fetch number and the subsequent fetches to 30 in your example code. If that does not repro on your end then maybe I've made a mistake elsewhere.

import React, { useEffect, useState } from 'react';
import { SafeAreaView, StyleSheet, Text, View } from 'react-native';

import { FlatList } from 'react-native-bidirectional-infinite-scroll';
import { MessageBubble } from './MessageBubble';
import { Message, queryMoreMessages } from './utils';

const App = () => {
  const [messages, setMessages] = useState<Array<Message>>([]);
  useEffect(() => {
    const initChat = async () => {
      const initialMessages = await queryMoreMessages(30);
      if (!initialMessages) return;

      setMessages(initialMessages);
    };

    initChat();
  }, []);

  const loadMoreOlderMessages = async () => {
    const newMessages = await queryMoreMessages(30);
    setMessages((m) => {
      return m.concat(newMessages);
    });
  };

  const loadMoreRecentMessages = async () => {
    const newMessages = await queryMoreMessages(30);
    setMessages((m) => {
      return newMessages.concat(m);
    });
  };

  if (!messages.length) {
    return null;
  }

  return (
    <SafeAreaView style={styles.safeArea}>
      <View style={styles.header}>
        <Text style={styles.headerTitle}>Chat between two users</Text>
      </View>
      <FlatList
        data={messages}
        inverted
        onEndReached={loadMoreOlderMessages}
        onStartReached={loadMoreRecentMessages}
        renderItem={MessageBubble}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  header: {
    alignItems: 'center',
    paddingVertical: 10,
    borderBottomColor: '#BEBEBE',
    borderBottomWidth: 1,
  },
  headerTitle: { fontSize: 20, fontWeight: 'bold' },
  safeArea: {
    flex: 1,
  },
  sendMessageButton: {
    width: '100%',
    padding: 20,
    backgroundColor: '#FF4500',
    alignItems: 'center',
  },
  sendButtonTitle: {
    color: 'white',
    fontSize: 15,
    fontWeight: 'bold',
  },
});

export default App;