开发者问题收集

在 React 中通过 firebase 使用 Map

2018-08-06
2980

请有人帮忙。我已梳理了所有文档,检查了所有类似的问题,但真的找不到我遗漏的内容。

我是 React 的新手,正在尝试映射从 Firebase 数据库的异步调用返回的文档。

这是代码:

class Posts extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        data: [],
    };
}
componentDidMount() {
    let posts = [];
    db.collection("Posts").get().then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            posts.push({
                data: doc.data(),
                id: doc.id
            });
        });
    });
    this.setState({
        data: posts
    });
}
renderPosts() {
    console.log(this.state.data);
    return this.state.data.map((post, index) => {
        console.log(post);
        console.log(index);
        return (
            <div>
                {index}
            </div>
        )
    })
}
render() {
    return(
        <div>
            {this.renderPosts()}
        </div>
    );
}
}

我确信这是一件非常简单的事情,但我正在抓狂。如果我检查我的状态,我可以看到数据。console.log(this.state.data); 里面的 renderPosts 甚至准确显示了我需要映射的内容,但 map 回调中的所有内容都没有返回,我最终得到一个空的。任何帮助都将不胜感激。

1个回答

正如 Li357 所评论的, setState 调用需要在 get() 回调内进行:

db.collection("Posts").get().then(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        posts.push({
            data: doc.data(),
            id: doc.id
        });
    });
    this.setState({
        data: posts
    });
});

这样做的原因是数据是从 Firestore 异步加载的,当您调用 setState 时, posts 变量仍然为空。

理解这种异步加载的最简单方法是使用几行日志:

console.log("Before starting to get documents");
db.collection("Posts").get().then(function(querySnapshot) {
    console.log("Got documents");
});
console.log("After starting to get documents");

运行此命令时,输出为:

Before starting to get documents

After starting to get documents

Got documents

这可能不是您预期输出的顺序。但这是预期的行为:不是在加载数据时阻止代码(这会冻结浏览器),而是立即执行 get().then() 块之后的代码。然后,当数据加载时,将执行 then 回调中的代码。这就是为什么所有需要从数据库获取文档的代码都需要位于 then 回调中的原因。

Frank van Puffelen
2018-08-06