Reputation: 842
I am working on the group functionality in my application and I want to be able to select multiple friends and add them together when creating the group like whatsapp.
But I am unable to pull this off. I have a parent component(AddMembers) and child component(AddMembersComp) being rendered in the Flatlist of the parent component. The problem I am facing is that my createGroup() method and a members array and each time the 'Add' button is pressed in the child component the associated userId gets pushed to the members array.
But what is happening instead is that a members array is being created for the each child component and on pressing the 'Add' button the uid is being pushed to that array associated with that specific component.
What I want to achieve is that I want push the uid's, on pressing the add button on each child component, into a universal array i.e associated with the whole list and not a specific component in the list. And then ultimately run a forEach to push the array to database.
Screenshot of the problem that is occuring:
As you can see that on tapping the 1st add button a new members array is created and the uid is pushed, but on tapping the 2nd add button another members array is created and the uid is pushed into that instead of being pushed into the old one. How can I fix this?? Please help.
This is my code:
//CHILD COMPONENT - AddMembersComp
class AddMembersComp extends Component {
constructor(props) {
super(props);
this.state = {
docId: '',
addedMembers: [],
};
this.email = this.props.email; //Props passed from the parent
this.username = this.props.username;
this.uid = this.props.uid;
this.name = this.props.name;
this.desc = this.props.desc; //Props passed from the parent
this.members = []; //Pushing uids into this array
}
async addMembers() { //Calling this on pressing the add button
await this.members.push(this.uid);
}
createGroup() {
var docRef = firestore()
.collection('Groups')
.doc();
firestore()
.runTransaction(transaction => {
return transaction.get(docRef).then(doc => {
this.setState({docId: doc.id});
transaction.set(docRef, {
name: this.name,
desc: this.desc,
createdOn: new Date(),
});
});
})
.then(() => {
console.log('this.members: ', this.members);
this.setState({addedMembers: this.members});
console.log('state members: ', this.state.addedMembers);
})
.then(() => {
this.state.addedMembers.forEach(member => {
firestore()
.collection('Groups')
.doc(`${this.state.docId}`)
.collection('Members')
.doc(`${member}`)
.set({
role: 'participant',
joinedOn: new Date(),
});
});
});
}
render() {
return (
<View>
<Text>{this.uid}</Text>
<Button
title="Add"
onPress={() => {
this.addMembers().then(() =>
console.log('State members: ', this.members),
);
}}
/>
</View>
);
}
}
// PARENT COMPONENT - AddMembersScreen
class AddMembersScreen extends Component {
constructor(props) {
super(props);
this.state = {
friends: [],
friendsData: [],
};
this.tempFriends = [];
this.tempFriendsData = [];
console.log('Add Members Screen');
this.name = this.props.navigation.getParam('name');
this.desc = this.props.navigation.getParam('desc');
}
componentDidMount() {
this.fetchFriends()
.then(() =>
this.setState({
friends: this.tempFriends,
}),
)
.then(() => this.fetchEachFriend());
}
async fetchFriends() {
const uid = auth().currentUser.uid;
await firestore()
.collection('Friendships')
.where('uid1', '==', `${uid}`)
.get()
.then(doc => {
if (doc.empty) {
null;
console.log('DOC: ', doc.empty);
} else {
doc.forEach(snap => {
console.log(snap.data().uid2);
this.tempFriends.push(snap.data().uid2);
console.log(this.tempFriends);
});
}
})
.catch(err => console.log('Error DOC1 ', err));
await firestore()
.collection('Friendships')
.where('uid2', '==', `${uid}`)
.get()
.then(doc => {
if (doc.empty) {
null;
console.log('DOC2: ', doc.empty);
} else {
doc.forEach(snap => {
console.log(snap.data().uid1);
this.tempFriends.push(snap.data().uid1);
console.log(this.tempFriends);
});
}
})
.catch(err => console.log('Error DOC2 ', err));
}
fetchEachFriend() { //Fetching each friends data to display
this.state.friends.forEach(uid => {
console.log('UID: ', uid);
firestore()
.collection('Users')
.doc(`${uid}`)
.get()
.then(doc => {
console.log('Friend Data ', doc.data());
this.tempFriendsData.push({
uid: doc.id,
data: doc.data(),
});
})
.then(() => this.setState({friendsData: this.tempFriendsData}))
.catch(err => {
console.log('Error fetchEachFriend(): ', err);
});
});
}
_renderItem = ({item}) => (
<View>
<AddMembersComp
email={item.data.email}
username={item.data.username}
uid={item.uid}
name={this.name}
desc={this.desc}
/>
</View>
);
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<FlatList
data={this.state.friendsData}
keyExtractor={(item, index) => index.toString()}
renderItem={this._renderItem}
/>
</View>
);
}
}
P.S I wondering that the solution could be something like this: Each time add button is pressed the uid gets sent to the parent component and gets pushed into a universal members array. But how should I pull that off??
Upvotes: 1
Views: 240
Reputation: 579
You need to handle the 'addedMembers' array in the parent something like this:
// PARENT COMPONENT - AddMembersScreen
class AddMembersScreen extends Component {
constructor(props) {
super(props);
this.state = {
friends: [],
friendsData: [],
addedMembers: []
};
this.tempFriends = [];
this.tempFriendsData = [];
console.log('Add Members Screen');
this.name = this.props.navigation.getParam('name');
this.desc = this.props.navigation.getParam('desc');
}
componentDidMount() {
this.fetchFriends()
.then(() =>
this.setState({
friends: this.tempFriends,
}),
)
.then(() => this.fetchEachFriend());
}
async fetchFriends() {
const uid = auth().currentUser.uid;
await firestore()
.collection('Friendships')
.where('uid1', '==', `${uid}`)
.get()
.then(doc => {
if (doc.empty) {
null;
console.log('DOC: ', doc.empty);
} else {
doc.forEach(snap => {
console.log(snap.data().uid2);
this.tempFriends.push(snap.data().uid2);
console.log(this.tempFriends);
});
}
})
.catch(err => console.log('Error DOC1 ', err));
await firestore()
.collection('Friendships')
.where('uid2', '==', `${uid}`)
.get()
.then(doc => {
if (doc.empty) {
null;
console.log('DOC2: ', doc.empty);
} else {
doc.forEach(snap => {
console.log(snap.data().uid1);
this.tempFriends.push(snap.data().uid1);
console.log(this.tempFriends);
});
}
})
.catch(err => console.log('Error DOC2 ', err));
}
fetchEachFriend() { //Fetching each friends data to display
this.state.friends.forEach(uid => {
console.log('UID: ', uid);
firestore()
.collection('Users')
.doc(`${uid}`)
.get()
.then(doc => {
console.log('Friend Data ', doc.data());
this.tempFriendsData.push({
uid: doc.id,
data: doc.data(),
});
})
.then(() => this.setState({friendsData: this.tempFriendsData}))
.catch(err => {
console.log('Error fetchEachFriend(): ', err);
});
});
}
handleMemberPress = (intUid) => {
const { addedMembers } = this.state
this.setState({
addedMembers: [...addedMembers, intUid]
})
}
_renderItem = ({item}) => (
<View>
<AddMembersComp
onPress={this.handleMemberPress}
email={item.data.email}
username={item.data.username}
uid={item.uid}
name={this.name}
desc={this.desc}
/>
</View>
);
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<FlatList
data={this.state.friendsData}
keyExtractor={(item, index) => index.toString()}
renderItem={this._renderItem}
/>
</View>
);
}
}
// CHILD COMPONENT - AddMembersComp
class AddMembersComp extends Component {
constructor(props) {
super(props);
this.state = {
docId: '',
addedMembers: [],
};
this.email = this.props.email; //Props passed from the parent
this.username = this.props.username;
this.uid = this.props.uid;
this.name = this.props.name;
this.desc = this.props.desc; //Props passed from the parent
this.members = []; //Pushing uids into this array
}
async addMembers() { //Calling this on pressing the add button
await this.members.push(this.uid);
}
createGroup() {
var docRef = firestore()
.collection('Groups')
.doc();
firestore()
.runTransaction(transaction => {
return transaction.get(docRef).then(doc => {
this.setState({docId: doc.id});
transaction.set(docRef, {
name: this.name,
desc: this.desc,
createdOn: new Date(),
});
});
})
.then(() => {
console.log('this.members: ', this.members);
this.setState({addedMembers: this.members});
console.log('state members: ', this.state.addedMembers);
})
.then(() => {
this.state.addedMembers.forEach(member => {
firestore()
.collection('Groups')
.doc(`${this.state.docId}`)
.collection('Members')
.doc(`${member}`)
.set({
role: 'participant',
joinedOn: new Date(),
});
});
});
}
handleOnPressMember = () => {
const { onPress } = this.props;
onPress(this.uid)
}
render() {
return (
<View>
<Text>{this.uid}</Text>
<Button
title="Add"
onPress={this.handleOnPressMember}
/>
</View>
);
}
}
Upvotes: 1