ComponenWillMount发生后出于某种原因回应原生

问题描述:

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中。然后我试图把它作为一个文本渲染。有些原因是空的或空的。这意味着componentWillMount()发生在渲染后()ComponenWillMount发生后出于某种原因回应原生

有人可以解释或使这项工作?我很沮丧。

我已经改变了代码,因为人们帮助我,但它仍然是给错误:

undefined is not a function (evaluating 'this.setState({ highscoreArray:sortedHighscores.reverse()})') 
+1

'.on()'是一个回调吗? “sortedHighscores”为空数组的原因可能是因为你需要在'.on()'回调中设置状态。 'setState'也可以是异步的,它的第二个参数有状态完成设置时的回调。 –

Data stored in a Firebase Realtime Database is retrieved by attaching an asynchronous listener to a database reference

按照documentation

因此,直到结果不知道,下面的代码this.state.highscoreArray[0]["score"].toString()将返回一个错误。在显示结果之前,请检查highscoreArray是否包含一些项目。

此外,检索数据不是一个好习惯。看看到React component lifecycle

componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state synchronously in this method will not trigger a re-rendering. Avoid introducing any side-effects or subscriptions in this method

基本上你不会等待所有得分其设置的状态,如果你把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?!?! 
} 

正如其他人所说,数据是从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分。在添加分数之前,我也清除了这个数组,因为这个value回调将在最后3个分数改变时被调用。所以这意味着您的分数会在UI中自动更新,例如当您在Firebase Database console中更改分数时。尝试一下。好有趣!

鉴于Andrew和Hennek的答案,您可能需要将此代码放入componentDidMount()。但是,您也需要在回调中拨打setState()

+0

你好,我已经改变了我的代码,并寻找进一步的指示。 console.log仍然给未定义 – chazefate