The idea I have for this to work is to copy my main array from firebase (Array with all my info) into a temporary array. Then I will filter this temporary array and have it displayed in flatlist. The onPress for the buttons serves to select the type of information to be filtered (Eg type 1 or 2 or 3).
import React, { useState, setState, useEffect } from 'react';
import { View, Text, StyleSheet, ImageBackground, FlatList, Button, TouchableHighlight } from 'react-native'
import Card from '../components/Card';
import colors from '../config/colors';
import {MaterialCommunityIcons} from '@expo/vector-icons'
import { useNavigation } from '@react-navigation/core';
import AppButton from '../components/AppButton'
import { SearchBar } from 'react-native-screens';
import { Firestore, getDoc, collection, getDocs,
addDoc, deleteDoc, doc,
query, where, onSnapshot
} from 'firebase/firestore';
import {db} from '../../firebase';
import { async } from '@firebase/util';
//run: 1
//swim: 2
//cycle: 3
function EventsPage(props) {
const [events, setEvents] = useState([]);
const [bool, setBool] = useState(false);
const [arr, setArr] = useState([])
const colRef = collection(db, 'events');
const q = query(colRef, where('type', '>=', 0))
onSnapshot(q, (snapshot) => {
const events = []
snapshot.docs.forEach((doc) => {
events.push({...doc.data()}) //put the data into an array
})
if (bool === false) {
setEvents(events);
setBool(true)
}
})
const updateSearch = search => {
setArr({ search }, () => {
if (type == search) {
setArr({
data: [...arr.temp]
});
return;
}
arr.data = arr.temp.filter(function(item){
return item.name.includes(search);
}).map(function({date, subTitle, title, type}){
return {date, subTitle, title, type};
});
});
};
return (
<View style = {styles.container}>
<ImageBackground
source = {require('../assets/splash-page.jpg')}
style = {{width: '100%', height: '100%'}}
blurRadius={8}
>
<View style = {styles.backIcon}>
<MaterialCommunityIcons name='arrow-left-bold' color="black" size={35} onPress={() => {
navigation.replace("Connect_me")
}} />
</View>
<Text style = {styles.text}>EVENTS</Text>
<View style = {styles.buttons}>
<Button title={'All'} />
<Button title={'Run'} onPress = {updateSearch(1)}/>
<Button title={'Swim'} onPress = {updateSearch(2)}/>
<Button title={'Cycle'} onPress = {updateSearch(3)}/>
</View>
<FlatList
data={arr.data}
renderItem={({ item }) => (
<View style = {styles.cardContainer}>
<Card title={item.title} subTitle = {item.subTitle}/>
</View>
)}
/>
<Text></Text>
<Text></Text>
<Text></Text>
<Text></Text>
<Text></Text>
</ImageBackground>
</View>
// trolling
);
}
const styles = StyleSheet.create({
text: {
fontSize: 80,
textAlign:'center',
paddingBottom: 20,
color: colors.primary,
fontWeight: 'bold',
},
container: {
backgroundColor: 'white',
},
cardContainer: {
width: '95%',
alignSelf: 'center'
},
backIcon: {
paddingLeft: 10,
paddingTop: 30,
},
searchIcon: {
paddingLeft: 10,
paddingTop: 15,
position: 'relative',
left: 330,
bottom: 47
},
buttons: {
flexDirection: 'row',
padding: 20,
}
})
export default EventsPage;
CodePudding user response:
Side effects code like listening to data change events should be handled inside the useEffect
hook.
The app continues to listen to data change events for each component re-render which causes an infinity loop.
useEffect(() => {
const unsubscribe = onSnapshot(q, (snapshot) => {
const events = [];
snapshot.docs.forEach((doc) => {
events.push({ ...doc.data() }); //put the data into an array
});
if (bool === false) {
setEvents(events);
setBool(true);
}
});
// unsubscribe to data change events when component unmount
return () => {
unsubscribe();
};
}, []);