在React Native中将数据从子组件传递到父组件?

时间:2019-11-07 21:00:55

标签: javascript arrays firebase react-native react-navigation

我正在开发应用程序中的群组功能,希望在创建类似whatsapp的群组时能够选择多个朋友并将其添加到一起。

但是我无法做到这一点。 我有一个父组件(AddMembers)和子组件(AddMembersComp)在父组件的平面列表中呈现。我面临的问题是我的createGroup()方法和一个成员数组,并且每次在子组件中按下“添加”按钮时,关联的userId都会被推送到成员数组。

但是正在发生的是,正在为每个子组件创建一个members数组,并在按下“添加”按钮时将uid推送到与该特定组件关联的那个数组。

我想要实现的是我想在按下每个子组件上的添加按钮时将uid推入通用数组,即与整个列表相关联,而不是与列表中的特定组件相关联。然后最终运行forEach将数组推送到数据库。

正在发生的问题的屏幕截图:

enter image description here

如您所见,在点击第一个添加按钮时,会创建一个新的成员数组,并推入uid,但是在点击第二个添加按钮时,会创建另一个成员数组,并且将uid推入其中,而不是将其推入旧的。 我怎样才能解决这个问题?? 请帮忙。

这是我的代码:

//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我想知道解决方案可能是这样的: 每次按下添加按钮时,uid都会发送到父组件,并被推入通用成员数组。但是我应该怎么做呢?

1 个答案:

答案 0 :(得分:1)

您需要像这样处理父级中的“ addedMembers”数组:

// 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>
    );
  }
}