从Firebase Firestore映射的渲染React组件

时间:2018-12-20 00:34:39

标签: javascript arrays reactjs firebase google-cloud-firestore

我花了几天的时间试图弄清楚这一点,希望大家都能帮助我。我想从Cloud Firestore数据库获取帖子,并将其显示在React应用上。

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

  

[项目] /新闻/ [文档]

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

  

[随机生成的ID]

     
      
  • 标题:[string]
  •   
  • body:[string]
  •   

我已经通过执行以下操作获取帖子:

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提取的对象数组上起作用?

预先感谢您的帮助!这让我很头疼。

3 个答案:

答案 0 :(得分:0)

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

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

}

此代码强调的要点是,反应是数据驱动的。本质上,您有一个称为发布的状态数组,您将在其上映射以呈现数据。当此数组为空时(例如在像初始渲染一样获取数据之前的情况),将不会渲染任何项目。一旦数据从数据库返回,数据就被添加到状态的posts数组中。调用setState方法以强制执行新的渲染,但这一次我们要显示数据。

如果此回答表明我误解了您的问题,请进行后续操作。

希望这会有所帮助!

答案 1 :(得分:0)

我已经解决了!

我并不是一成不变地更改它。

这可以使其正常工作:

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 :(得分:0)

您对问题的答案仍然缺少右键。因此,对芒果问题的完整答案(以及自己的答案)将是:

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

}