I am using React-Native
and React-Native-Firebase
and am trying to have my Events
component make a different Firebase query (and then update redux store) depending what the value of the activityType prop is.
Here is the parent component which is working just fine. It updates state.eventType when I change the dropdown value and passes the value into <Events />
.
let eventTypes = [{value: 'My Activity'}, {value: 'Friend Activity'}, {value: 'All Activity'}];
state = {
showEventFormModal: false,
eventType: 'Friend Activity'
}
<View style={styles.container}>
<Dropdown
data={eventTypes}
value={this.state.eventType}
containerStyle={{minWidth: 200, marginBottom: 20}}
onChangeText={val => this.setState({eventType: val})}
/>
<Events activityType={this.state.eventType}/>
</View>
And here is Events component. Using a Switch
statement to determine which activityType was passed into props. The issue I am having is an infinite loop because within each case statement I am dispatching the action to update the store which causes a rerender and the componentWillUpdate() to retrigger. What I am trying to understand is what the optimal way to handle this problem is? Because clearly my method now does not function properly. Is there a common react pattern to achieve this?
// GOAL: when this components props are updated
// update redux store via this.props.dispatch(updateEvents(events))
// depending on which type of activity was selected
componentWillUpdate() {
let events = [];
switch(this.props.activityType) {
case 'Friend Activity': // get events collections where the participants contains a friend
// first get current users' friend list
firebase.firestore().doc(`users/${this.props.currentUser.uid}`)
.get()
.then(doc => {
return doc.data().friends
})
// then search the participants sub collection of the event
.then(friends => {
firebase.firestore().collection('events')
.get()
.then(eventsSnapshot => {
eventsSnapshot.forEach(doc => {
const { type, date, event_author, comment } = doc.data();
let event = {
doc,
id: doc.id,
type,
event_author,
participants: [],
date,
comment,
}
firebase.firestore().collection('events').doc(doc.id).collection('participants')
.get()
.then(participantsSnapshot => {
for(let i=0; i<participantsSnapshot.size;i++) {
if(participantsSnapshot.docs[i].exists) {
// if participant uid is in friends array, add event to events array
if(friends.includes(participantsSnapshot.docs[i].data().uid)) {
// add participant to event
let { displayName, uid } = participantsSnapshot.docs[i].data();
let participant = { displayName, uid }
event['participants'].push(participant)
events.push(event)
break;
}
}
}
})
.then(() => {
console.log(events)
this.props.dispatch(updateEvents(events))
})
.catch(e => {console.error(e)})
})
})
.catch(e => {console.error(e)})
})
case 'My Activity': // get events collections where event_author is the user
let counter = 0;
firebase.firestore().collection('events').where("event_author", "==", this.props.currentUser.displayName)
.get()
.then(eventsSnapshot => {
eventsSnapshot.forEach(doc => {
const { type, date, event_author, comment } = doc.data();
let event = {
doc,
id: doc.id,
type,
event_author,
participants: [],
date,
comment,
}
// add participants sub collection to event object
firebase.firestore().collection('events').doc(event.id).collection('participants')
.get()
.then(participantsSnapshot => {
participantsSnapshot.forEach(doc => {
if(doc.exists) {
// add participant to event
let { displayName, uid } = doc.data();
let participant = { displayName, uid }
event['participants'].push(participant)
}
})
events.push(event);
counter++;
return counter;
})
.then((counter) => {
// if all events have been retrieved, call updateEvents(events)
if(counter === eventsSnapshot.size) {
this.props.dispatch(updateEvents(events))
}
})
})
})
case 'All Activity':
// TODO
// get events collections where event_author is the user
// OR a friend is a participant
}
}