【问题标题】:How to get all document fields in a subcollection appear at the same time如何让子集合中的所有文档字段同时出现
【发布时间】:2020-03-26 03:08:58
【问题描述】:

我只需要一些帮助来获取 firestore 数据库上的文档字段。链接上的示例图像image sample here 是我的用户子集。我试图获取所有文档字段“groupName”并使其全部显示在屏幕上。使用我正在使用的代码,屏幕上只显示一个字段。

  class CreateNewGroup extends Component {
  constructor(props) {
     super(props);
     this.state = ({
       groupName: '',
       loading: false,

    });
  };

  getCoordinates(query) {
    console.log('start loading animation');
  };

 MountFSUserGroup = () => {
 const curUser = firebase.auth().currentUser;

 const dbUser =
  firebase
  .firestore()
  .collection('users')
  .doc(curUser.uid)
  .collection('SampleGroup') 
  .get()  
  .then(snapshot => {
     if (snapshot.empty) {
        console.log('No matching documents.');
        return;
     }  
     snapshot.forEach(doc => {
        console.log(doc.id, '=>', doc.data()); 
        const { groupName } = doc.data();
        this.setState({ groupName, loading: false }); 

     });
   })
   .catch(err => {
        console.log('Error getting documents', err);
   });  

  const { groupName } = dbUser;
  this.setState({ groupName, loading: true }); 
  };


  componentDidMount() {
    this.MountFSUserGroup()
  }; 

  UNSAFE_componentWillMount() {
    this.MountFSUserGroup()
    console.log("user group mounted");
  };      


  render() {

  return (
     <View style={{flex: 1,}}>
        <CustomHeaderBack />
        <Loader loading={this.state.loading} />

        <ScrollView>
        <View style={styles.body}>
              <View style={styles.titleCont}>
              <Text 
                 style={styles.text1}>
                    SAMPLE GROUP LIST
              </Text>         
              </View> 

              <View style={styles.insideCont}>
              <Text 
                 style={styles.text2}>
                    Select Your Group:
              </Text>


              <Text 
                 style={styles.text2}>
                    {this.state.groupName}

              </Text>


              </View>
        </View>
        </ScrollView>
        <CustomFooter />
     </View>    
     )
    }
    };

     export default CreateNewGroup ;

Sample screen 仅显示第三个字段“groupName: "Group Three"”,但在控制台上(console log sample) 同时列出了所有字段。

如果我使用

  .where('groupName', "==", true)

它转到空的错误消息“没有匹配的文档”并且屏幕冻结。希望有人能帮忙。提前致谢。

【问题讨论】:

  • 等等..你只是存储一个组名..所以我猜它显示的是最后一个。我认为这不是数据检索问题,因为您的控制台日志似乎没问题。我认为您需要 snapshot.map() 并将其设置为您的组件状态(假设反应)
  • 是的,我正在使用 react native cli。我确实尝试了 snapshot.docs.map() 但结果仍然相同,控制台记录了所有文档字段,但与不使用地图相比,屏幕上没有显示任何内容。
  • 我刚才也做了snapshot.map(),它只是在不断加载。
  • 嗯.. 你在哪里有这个代码?它可能在渲染/安装时被调用并正在改变状态,导致组件渲染,它正在调用 fn 等等。您可能想在条件下调用它..或者如果您正在使用钩子,请将调用包装在 useEffect.. 中以当前用户 ID 为条件?大概……
  • 此代码来自 firebase 文档。该功能在组件内部。我对钩子不是很熟悉,我还有很多东西要学。

标签: javascript firebase react-native google-cloud-firestore


【解决方案1】:

目前的代码存在几个问题。

this.setState({ groupName, loading: false }); - 这只是将最后遇到的 groupName 设置为组件状态。这是原来的问题。你必须snapshot.map()

如果它不断地重新渲染,那么这个 fn 可能在渲染周期的某个地方被调用。作为一般原则,最好尽可能区分数据检索和状态管理。因此,如果您将 getGroupNames 移动到它自己的函数中,并提供用户 ID 和 firebase 实例,那么您可以将值设置为 state,只有当它与以前的值不同时。

或者,如果您正在使用挂钩,如果可以的话,我强烈建议您使用 useMemo 或使用 useEffect 设置呼叫,具体取决于用户 ID。无论哪种方式,都会将调用限制为仅在需要时进行。

这样可以吗?

//...imports...

class CreateNewGroup extends Component {
  constructor(props) {
     super(props);
     this.state = ({
       groupNames: [],
       loading: false,
    });
  };

//i might even take this out of the component and declare it as a pure js function
// as it is not using anything from 'this' and loading can be set where it is being called from too
 getFSUserGroup = async () => {
    try {
        this.setState({ loading: false })
        const curUser = firebase.auth().currentUser;

        // get some value
        const data = async firebase
            .firestore()
            .collection('users')
            .doc(curUser.uid)
            .collection('SampleGroup') 
            .get()  
            .map(doc =>  doc.data().groupName); // get all the group names for each item
        this.setState({ loading: false }) // set loading as false, will trigger a render
        return data // return that data from above
    } catch (e) {
        // failed to get documents
        this.setState({ loading: false })
    }// if it errored or something, it would return undefined
}


  componentDidMount() {
    this.getFSUserGroup().then(x => {
        if (x && !this.state.groupNames) {
            this.setState({ groupNames })
        }
        // it might not be a great idea to simply `!this.state.groupNames` though.. :(
    })


  }; 
// render and other stuff

另外,如果你刚开始.. 看看React Stateless Function Components 可能是个好主意,因为这样你就可以使用Hooks 除其他外,它巧妙地抽象了许多涉及执行简单任务(例如您正在执行的任务)的样板代码。 有关原因和方法的详细介绍,请查看this one

【讨论】:

  • 我对钩子不是很熟悉。我仍然是 react native 的初学者
  • 它说 .map' 未定义....我确实尝试在之前的代码中使用 Flatlist,它现在显示在屏幕上,但屏幕上显示的文本显示“未定义”超过 10 倍。是的,我认为是时候学习钩子了。
  • 终于解决了我的问题,而不是使用地图,我使用 push for doc.data() 我也在这个网站上发现了与我类似的问题
猜你喜欢
  • 2021-12-16
  • 2016-12-28
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 2019-12-29
  • 1970-01-01
  • 2016-01-06
相关资源
最近更新 更多