'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 |
