componentDidMount() {
const refi = database.ref("highscores");
// Pushing sorted data to highscoreArray.
refi.orderByChild("highscore").limitToLast(3).on("value", function(snapshot) {
sortedHighscores = [];
snapshot.forEach(function(child) {
sortedHighscores.push({
"username" : child.val().username,
"score" : child.val().highscore
});
});
sortedHighscores.sort(function(a,b) {
return a.score - b.score;
});
this.setState({highscoreArray : sortedHighscores.reverse()});
});
console.log("highscore is:", this.state.highscoreArray);
}
我正在尝试从数据库中获取数据并将其放在highscoreArray中。然后我试图把它作为渲染中的文本。某些原因它是空的或null。这意味着componentWillMount()发生在render()
之后有人可以解释或做这项工作吗?我很沮丧。
我已经更改了代码,因为人们帮助了我,但仍然是错误:
undefined is not a function (evaluating 'this.setState({ highscoreArray:sortedHighscores.reverse()})')
答案 0 :(得分:1)
通过将异步侦听器附加到数据库引用
来检索存储在Firebase实时数据库中的数据
因此,在结果不知道之前,以下代码this.state.highscoreArray[0]["score"].toString()
将返回错误。在显示结果之前,请检查highscoreArray
是否包含某些项目。
此外,检索数据不是一个好习惯。看看React component lifecycle:
在安装发生之前立即调用componentWillMount()。它在render()之前调用,因此在此方法中同步设置状态不会触发重新呈现。避免在此方法中引入任何副作用或订阅
答案 1 :(得分:0)
基本上你没有等待所有分数在设置到状态之前被推送,如果你将componentWillMount变成异步函数我相信它会解决你的问题:
async componentWillMount() {
sortedHighscores = [];
const refi = database.ref("highscores");
// Pushing sorted data to highscoreArray.
await refi.orderByChild("highscore").limitToLast(3).on("child_added", function(snapshot) {
sortedHighscores.push({
"username" : snapshot.val().username,
"score" : snapshot.val().highscore});
});
sortedHighscores.sort(function(a,b) {
return a.score - b.score;
});
this.setState({highscoreArray : sortedHighscores.reverse()});
console.log("highscorevvvvv", sortedHighscores);//this.state.highscoreArray) // these are EMPTY?!?!
}
答案 2 :(得分:0)
正如其他人所说,数据是从Firebase异步读取的。在读取数据时,使用空数组调用setState()
。然后,当数据返回时,您将其添加到数组中,但不再调用setState()
。
解决方案是将调用setState()
移动到读取(或更改)数据时触发的回调中:
refi.orderByChild("highscore").limitToLast(3).on("value", function(snapshot) {
sortedHighscores = [];
snapshot.forEach(function(child) {
sortedHighscores.push({
"username" : child.val().username,
"score" : child.val().highscore
});
});
sortedHighscores.sort(function(a,b) {
return a.score - b.score;
});
this.setState({highscoreArray : sortedHighscores.reverse()});
});
你会注意到我正在听一个value
事件,这可以确保我一次性获得所有3个分数。我还在添加分数之前清除了数组,因为只要最后3个分数发生变化,就会调用此value
回调。因此,这意味着当您在Firebase Database console中更改分数时,您的分数将在UI中自动更新。试试吧。这很有趣!
鉴于Andrew和Hennek的答案,您可能希望将此代码放在componentDidMount()
中。但也有,你需要在回调中调用setState()
。