'How build bidirectional infinite scroll flat listwith javascript no typescript

I am usig react native with javascript, no typescript, and I want use flatlist "react-native-bidirectional-infinite-scroll" but I don't found example in javascript.

How I create flatlist that go to top and bottom with more items?

Thanks



Solution 1:[1]

react-native-bidirectional-infinite-scroll authors example with TypeScript code convert to vanilla JavaScript.

utils.js file



// Generate random integer, we will use this to use random message from list of dummy messages.
export const getRandomInt = (min, max) => {
 return Math.floor(Math.random() * (max - min)) + min;
};

// Generate unique key for message component of FlatList.
export const generateUniqueKey = () =>
 `_${Math.random().toString(36).substr(2, 9)}`;

// List of test messages to generate chat data.
export const testMessages = [
 'Hey, where were you yesterday? I was trying to call you',
 'Yeah dude!! Had a really bad night. I was really hungover',
 'lol, thats so typical you. Who did you go out with?',
 'Dont even ask me about it, I am never going drink with Uthred again. That dude is a beast',
 'hahahaha, I can totally imagine!!',
 'Ciao :)',
];
 


/**
* Mocks the api call to query `n` number of messages.
* We are going to add some timeout before returning the result to simulate an api call over network.
* 
* We are going to generate two types of message:
* - sent message
* - received message
* 
* This will be controlled by a boolean property on message object - `isMyMessage`.
* This will be randomly assigned to message, based on result of getRandomInt.
* These two messages will be styled differently, which is the case for most of the
* popular messaging applications e.g., whatsapp, messenger
* 
* @param n {number} Number of new messages to query
* @param networkLatency {number} Number of milliseconds, to simulate api call.
*/
export const queryMoreMessages  = (n, networkLatency = 100) => {
 return new Promise((resolve) => {
   const newMessages = [];

   for (let i = 0; i < n; i++) {
     const messageText = testMessages[getRandomInt(0, testMessages.length)];
     newMessages.push({
       id: generateUniqueKey(),
       text: messageText,
       isMyMessage: Boolean(getRandomInt(0, 2)), // Randomly assign true or false.
     });
   }

   // Lets resolve after 500 ms, to simulate network latency.
   setTimeout(() => {
     resolve(newMessages);
   }, networkLatency);
 });
};

MessageBubble.js file

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

/**
 * UI Component for message item, in message list (FlatList).
 */
export const MessageBubble = ({item}) => {
  if (item.isMyMessage) {
    // Align sent messages to right side of the screen, with a grey'ish background.
    return (
      <View
        key={`${item.id}`}
        style={[styles.messageBubble, styles.myMessageBubble]}>
        <Text style={styles.myMessageText}>{item.text}</Text>
      </View>
    );
  }

  // Align received messages to left side of the screen, with blue background.
  return (
    <View key={`${item.id}`} style={styles.messageBubble}>
      <Text style={styles.messageText}>{item.text}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  messageBubble: {
    maxWidth: 300,
    padding: 10,
    borderRadius: 10,
    marginVertical: 5,
    marginHorizontal: 5,
    backgroundColor: '#F1F0F0',
  },
  myMessageBubble: {
    alignSelf: 'flex-end',
    backgroundColor: '#3784FF',
  },
  messageText: {
    fontSize: 15,
  },
  myMessageText: {
    color: 'white',
    fontSize: 15,
  },
});


App.js

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

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

// Counter to keep track of how many times `loadMoreRecentMessages` function has been called.
// We want to simulate a UX where user has scrolled till the most recent message available in
// chat. So for our example, we are going stop querying (and appending) new messages to the screen,
// once loadMoreRecentCounter is greater than 2.
// In real chat applications, you generally receive a flag from pagination api, which tells the app
// if user is at the most recent message in chat or not. 
let loadMoreRecentCounter = 0;

const App = () => {
  const [messages, setMessages] = useState();
  const [enableAutoscrollToTop, setEnableAutoscrollToTop] = useState(false);
  useEffect(() => {
    // When app is opened, we are going to render 50 messages on screen.
    // Generally this is where you connect to chat server and query first batch of messages.
    const initChat = async () => {
      const initialMessages = await queryMoreMessages(50, 0);
      setMessages(initialMessages);
    };

    initChat();
  }, []);

  // Add 10 more messages to end of the list.
  // In real chat application, this is where you have your pagination logic.
  const loadMoreOlderMessages = async () => {
    const newMessages = await queryMoreMessages(10);
    setMessages((m) => {
      return m.concat(newMessages);
    });
  };

  // Add 10 more messages to beginning of the list.
  // In real chat application, this is where you have your pagination logic.
  const loadMoreRecentMessages = async () => {
    if (loadMoreRecentCounter > 2) {
      // User is at the most recent message in chat.
      !enableAutoscrollToTop && setEnableAutoscrollToTop(true);
      return;
    }

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

    loadMoreRecentCounter += 1;
  };

  /**
   * Simulates a send message feature of Chat applications. It simply adds a randomly
   * generated message at beginning of the list - it can either be a sent or received message.
   */
  const sendMessage = async () => {
    const newMessages = await queryMoreMessages(1, 0);
    setMessages((m) => {
      return newMessages.concat(m);
    });
  };

  if (!messages) {
    // If the messages are not ready, lets not show anything.
    // Generally you can render some kind of loading indicator in this case.
    return null;
  }

  /**
   * NOTE:
   * 
   * - You can also control the scroll offset, at which `onEndReached` and `onStartReached`
   *   should be called, using props - onEndReachedThreshold and onStartReachedThrehols
   * - We are using `inverted` FlatList, since thats a common UX for Chat applications.
   */
  return (
    <SafeAreaView style={styles.safeArea}>
      <View style={styles.header}>
        <Text style={styles.headerTitle}>Chat between two users</Text>
      </View>
      <FlatList
        data={messages}
        inverted
        enableAutoscrollToTop={enableAutoscrollToTop}
        onEndReached={loadMoreOlderMessages}
        onStartReached={loadMoreRecentMessages}
        renderItem={MessageBubble}
      />
      <TouchableOpacity onPress={sendMessage} style={styles.sendMessageButton}>
        <Text style={styles.sendButtonTitle}>Send message</Text>
      </TouchableOpacity>
    </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;

Expo snack - https://snack.expo.dev/@emmbyiringiro/cffec2

Note: Don't test with the web version, test with android or iOS

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Shy Penguin