Skip to content

Instantly share code, notes, and snippets.

@victorwpbastos
Created May 22, 2020 16:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save victorwpbastos/488863eac3ad2d91dc1e6ef3ada25ccd to your computer and use it in GitHub Desktop.
Save victorwpbastos/488863eac3ad2d91dc1e6ef3ada25ccd to your computer and use it in GitHub Desktop.
Better performance paginated FlatList
import React, { useState, useEffect } from 'react';
import { Text, FlatList, View, TextInput, TouchableOpacity } from 'react-native';
let arr: any[] = [];
for (let i = 1; i <= 100; i++) {
arr.push({ id: i, text: `mensagem bacana #${i}` });
}
arr.reverse();
const api = {
fetchMessages(page: number = 1): Promise<any[]> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(arr.slice(20 * (page - 1), 20 * page));
}, 1000);
});
},
};
const Message: React.FC<any> = ({ text }) => {
return (
<View style={{ padding: 10, backgroundColor: '#ffffff', elevation: 2, marginBottom: 10 }}>
<Text>{text}</Text>
</View>
);
};
const Main: React.FC = () => {
const [messages, setMessages] = useState<any[]>([]);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const [text, setText] = useState<string>('');
const [fetching, setFetching] = useState(false);
const [onEndReachedCalledDuringMomentum, setOnEndReachedCalledDuringMomentum] = useState(true);
useEffect(() => {
async function fetchMessages(page = 1) {
console.log('called fetchmessages', page);
setFetching(true);
const response = await api.fetchMessages(page);
setTotalPages(5);
// setMessages((data) => [...data, ...response]);
setMessages((data) => {
const items = [...data, ...response];
const uniqueIds = [...new Set(items.map((item) => item.id))];
return uniqueIds.map((id) => items.find((item) => item.id === id));
});
setFetching(false);
}
fetchMessages(currentPage);
const interval = setInterval(fetchMessages, 5000);
return () => clearInterval(interval);
}, [currentPage]);
function handleAddMessage() {
setMessages([{ id: Date.now(), text }, ...messages]);
setText('');
}
function goToNextPage() {
if (!onEndReachedCalledDuringMomentum) {
if (fetching || (totalPages > 0 && currentPage >= totalPages)) {
return;
}
console.log('called gotonextpage', currentPage);
setCurrentPage((data) => data + 1);
setOnEndReachedCalledDuringMomentum(true);
}
}
return (
<>
<FlatList
data={messages}
keyExtractor={(item) => String(item.id)}
renderItem={({ item }) => <Message text={item.text} />}
inverted={true}
onEndReached={goToNextPage}
onEndReachedThreshold={0.25}
onMomentumScrollBegin={() => setOnEndReachedCalledDuringMomentum(false)}
/>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<TextInput
value={text}
onChangeText={setText}
placeholder="Digite sua mensagem"
style={{ flex: 1, height: 50, borderWidth: 1, borderColor: 'lightseagreen' }}
/>
<TouchableOpacity
style={{
justifyContent: 'center',
height: 50,
padding: 10,
borderWidth: 1,
borderColor: 'lightseagreen',
backgroundColor: 'lightseagreen',
}}
onPress={handleAddMessage}>
<Text style={{ fontWeight: 'bold', color: '#ffffff' }}>Enviar</Text>
</TouchableOpacity>
</View>
</>
);
};
export default Main;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment