Skip to content

Instantly share code, notes, and snippets.

@vishalnarkhede
Last active March 1, 2021 09:41
Show Gist options
  • Save vishalnarkhede/5712c0922e12f927ad65053f9ce3fe25 to your computer and use it in GitHub Desktop.
Save vishalnarkhede/5712c0922e12f927ad65053f9ce3fe25 to your computer and use it in GitHub Desktop.
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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment