渲染从 Firebase Firestore 映射的 React 组件

Posted

技术标签:

【中文标题】渲染从 Firebase Firestore 映射的 React 组件【英文标题】:Rendering React components mapped from Firebase Firestore 【发布时间】:2019-05-20 12:33:40 【问题描述】:

我已经花了几天的时间试图解决这个问题,希望大家能帮助我。我想从 Cloud Firestore 数据库中获取帖子并将其显示在 React 应用上。

我在 Firestore 中的数据结构如下:

[项目]/NewsPosts/[文档]

每个文档在 Firestore 中的结构如下:

[随机生成的id]

标题:[字符串] 正文:[字符串]

我通过执行以下操作获得了帖子:

let posts= [];

//db = firebase.firestore();

db.collections.("NewsPosts").get().then((snapshot) => (
  snapshot.forEach((doc) => (
    posts.push(
      id: doc.id,
      title: doc.data().title,
      body: doc.data().body
    )
  ))
));

这成功地创建了一个包含我想要的信息的对象数组,因此获取数据不是问题。然而,当我去映射这个数组来创建帖子时,什么都没有被创建。我已经尝试了映射数组的所有变体来创建组件,但它不起作用。

但是,当我对一组对象进行硬编码并映射该对象时,它就可以工作了。例如,这适用于硬编码的对象数组:

//hard is the hardcoded array
let displayPosts = hard.map((p) => (
    <div key=p.id>
        <h1>p.title</h1>
        <p>p.body</p>
    </div>
))

return(
    <Page>
        displayPosts
    </Page>
);

当我在浏览器控制台中比较硬编码数组和其他数组时,数组看起来不同。

我想是数组中的这种差异导致了问题。

如果有 2 个元素,这就是它们在浏览器控制台中的外观:

(2)[...,...]      (hardcoded)
[]                    (array filled from firestore)

但是,关于数组的其他所有内容在浏览器控制台中都是相同的。

为什么这些数组看起来不同?这是让我无法正确映射每个索引处的对象的原因吗?如何让映射作用于从 Firestore 获取的对象数组?

提前感谢您的帮助!这让我很头疼。

【问题讨论】:

你能告诉鳕鱼在哪里尝试映射数组吗? 当然!我编辑了我的原始帖子以添加它 【参考方案1】:

我已经解决了!

我并没有一成不变地改变它。

这使它正常工作:

constructor(props)
    super(props);

    this.state = 
        posts: []
    


componentDidMount = () => 
    db.collection("NewsPosts").get().then((snapshot) => (
        snapshot.forEach((doc) => (
            this.setState((prevState) => (
                posts: [...prevState.posts, 
                    postID: doc.id,
                    title: doc.data().title,
                    body: doc.data().body,
                    featured: doc.data().featured
                ]
            ))
        ))
    ))

【讨论】:

我已经多次遇到这个问题,并不断回到这个答案。总是修复它!【参考方案2】:

您对问题的回答仍然缺少正确的键。因此,Mango 问题的完整答案(以及自己的答案)将是:

class Sample extends React.Component 

constructor(props)
  super(props);

  this.state = 
    posts: []
  


componentDidMount = () => 
    db.collection("NewsPosts").get().then((snapshot) => (
        snapshot.forEach((doc) => (
            this.setState((prevState) => (
                posts: [...prevState.posts, 
                    postID: doc.id,
                    title: doc.data().title,
                    body: doc.data().body,
                    featured: doc.data().featured
                ]
            ))
        ))
    ))


    render() 
        let displayPosts = this.state.posts.map((p) => (
            <div key=p.postID>
                <h1>p.title</h1>
                <p>p.body</p>
            </div>
        ))

        return(
            <Page>
                displayPosts
            </Page>
        );
    


【讨论】:

【参考方案3】:

根据我对您问题的理解,我认为以下代码应该可以帮助您解决问题。

class Sample extends React.Component 

    state = 
        posts: []
    

    componentDidMount() 
        let posts = [];
        db.collections.("NewsPosts").get().then((snapshot) => (
            snapshot.forEach((doc) => (
                posts.push(
                    id: doc.id,
                    title: doc.data().title,
                    body: doc.data().body
                )
            ))
            this.setState( posts )
        ));
    

    render() 
        let displayPosts = this.state.posts.map((p) => (
            <div key=p.id>
                <h1>p.title</h1>
                <p>p.body</p>
            </div>
        ))

        return(
            <Page>
                displayPosts
            </Page>
        );
    


这段代码强调的要点是,react 是数据驱动的。本质上,您有一个名为 posts 的状态数组,您将映射到该数组以呈现您的数据。当这个数组为空时,就像在初始渲染时获取数据之前的情况一样,不会渲染任何项目。一旦数据从数据库返回,数据就会添加到您的帖子数组中。调用setState 方法来强制进行新的渲染,但这次我们有数据要显示。

如果此答案表明我误解了您的问题,请继续跟进。

希望这会有所帮助!

【讨论】:

感谢您的回答!不幸的是,这不起作用。什么都没有显示。我不确定这些帖子是否会被添加到数组中,但我稍后必须对其进行测试。

以上是关于渲染从 Firebase Firestore 映射的 React 组件的主要内容,如果未能解决你的问题,请参考以下文章

将 Firebase 身份验证用户映射到 Firestore 文档

从 Firestore 获取数据并将其映射到提供程序对象

Firestore - 如何从值映射中添加/减去

Firebase Firestore toObject 在布尔属性映射上失败

在 Firebase Firestore 中映射集合快照项

使用 Stream 从 FireStore 获取数据并将其映射到 Flutter 类