yashatreya
yashatreya

Reputation: 842

Passing data from child component to parent component in react native?

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:

enter image description here

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

Answers (1)

J.T
J.T

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

Related Questions