将 componentWillUpdate 与 switch 语句一起使用
Using componentWillUpdate with switch statements
我正在使用 React-Native
和 React-Native-Firebase
并试图让我的 Events
组件根据 activityType 的值进行不同的 Firebase 查询(然后更新 redux 存储)道具是。
这是工作正常的父组件。当我更改下拉值并将该值传递给 <Events />
.
时,它会更新 state.eventType
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>
这里是事件组件。使用 Switch
语句来确定哪个 activityType 被传递到道具中。我遇到的问题是一个无限循环,因为在每个 case 语句中我都在分派更新商店的操作,这会导致重新呈现和 componentWillUpdate() 重新触发。我想了解的是处理此问题的最佳方法是什么?因为显然我的方法现在无法正常运行。是否有通用的反应模式来实现这一目标?
// 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
}
}
更新商店最好在用户操作上进行。因此,我会在 Dropdown
onChange 事件和 componentWillUpdate 函数中更新商店。
在发现我可以通过 componentDidUpdate
访问 prevProps
之后,我想出了一种处理这个问题的干净方法。这样我就可以将之前的 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
我正在使用 React-Native
和 React-Native-Firebase
并试图让我的 Events
组件根据 activityType 的值进行不同的 Firebase 查询(然后更新 redux 存储)道具是。
这是工作正常的父组件。当我更改下拉值并将该值传递给 <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>
这里是事件组件。使用 Switch
语句来确定哪个 activityType 被传递到道具中。我遇到的问题是一个无限循环,因为在每个 case 语句中我都在分派更新商店的操作,这会导致重新呈现和 componentWillUpdate() 重新触发。我想了解的是处理此问题的最佳方法是什么?因为显然我的方法现在无法正常运行。是否有通用的反应模式来实现这一目标?
// 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
}
}
更新商店最好在用户操作上进行。因此,我会在 Dropdown
onChange 事件和 componentWillUpdate 函数中更新商店。
在发现我可以通过 componentDidUpdate
访问 prevProps
之后,我想出了一种处理这个问题的干净方法。这样我就可以将之前的 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