Using componentWillUpdate with switch statements

时间:2018-09-18 20:12:46

标签: reactjs firebase react-native google-cloud-firestore react-native-firebase

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

2 个答案:

答案 0 :(得分:1)

最好根据用户操作来更新商店。因此,我将在Dropdown onChange事件和componentWillUpdate函数中更新商店。

答案 1 :(得分:0)

在发现我可以通过prevProps访问componentDidUpdate之后,我想出了一种干净的处理方式。这样,我可以将以前的activityType与当前的activityType进行比较,如果它们已更改,则在componentDidUpdate上应该调用fetchData(activityType)

class Events extends React.Component {

 componentDidMount() {
     // for initial load 
     this.fetchData('My Activity')
 }

 componentDidUpdate(prevProps) {     
     if(this.props.activityType !== prevProps.activityType) {
         console.log(`prev and current activityType are NOT equal. Fetching data for ${this.props.activityType}`)
         this.fetchData(this.props.activityType)
     }
 } 
 fetchData = (activityType) => {
    //switch statements deciding which query to perform
      ...
      //this.props.dispatch(updateEvents(events))
 }

}

https://reactjs.org/docs/react-component.html#componentdidupdate