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

标签 javascript arrays firebase react-native react-navigation

我正在开发我的应用程序中的群组功能,我希望能够在创建群组(如 whatsapp)时选择多个 friend 并将他们添加在一起。

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

但实际上正在为每个子组件创建一个成员数组,并在按下“添加”按钮时将 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 都会发送到父组件并被插入通用成员数组。但我该如何实现呢??

最佳答案

您需要像这样处理父级中的“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>
    );
  }
}

关于javascript - 在 React Native 中将数据从子组件传递到父组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58756853/

相关文章:

Java:如何将文本文件中的所有单词保存在字符串数组上

c++ - 如何获得在 C++ 中生成字母表的更简单方法?

C 程序不断返回 1

android - 错误 : not an enclosing class: MainActivity

javascript - jquery附加按钮单击显示文本然后消失

javascript - Angular 单元测试服务元素持久性

javascript - 如何在 d3 力定向顶点中显示徽章

android - Firebase UI gradle 无法解析 'com.firebaseui.firebase-ui:0.2.0'

javascript - 如何循环每个文档并获取其数据

javascript - 将自定义标记添加到 Mapbox map