ComponenWillMount在渲染后由于某种原因在本机中发生

时间:2017-07-03 21:01:29

标签: javascript reactjs firebase react-native

    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()})')

3 个答案:

答案 0 :(得分:1)

  

通过将异步侦听器附加到数据库引用

来检索存储在Firebase实时数据库中的数据

根据documentation

因此,在结果不知道之前,以下代码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()