在ReactJS中手动刷新Firebase对象

时间:2018-02-02 04:08:09

标签: javascript reactjs firebase firebase-realtime-database

我有一个小应用程序,用户可以在其中输入人名并将其添加到棋盘上然后用户可以向上或向下投票(对于幻想足球)。目前,在不需要刷新页面的情况下立即发生的唯一事情是通过文本输入框添加播放器时。这会为对象带来一点点淡入,它就会出现在屏幕上:

addPlayer(player) {

this.state.user ?
  this.database.push().set({ playerContent: player, votes: 0})
  :
  console.log("Not Logged In")
}

这是否是实时完成的,因为它是推动力?在用户投票后我怎么能更新玩家董事会?现在,当说Jane Doe有两张选票,并且John Doe有2票并且你将John Doe投票到3票时,他不会在Jane Doe之前跳起来直到刷新页面。在投票时有没有办法刷新每个单独的对象?这是我的投票代码

upvotePlayer(playerId) {
if(this.state.user) {
  let ref = firebase.database().ref('/players/' + playerId + '/voters');

  ref.once('value', snap => {
    var value = snap.val()
    if (value !== null) {            
        ref.child(this.uid).once('value', snap => {
          if (snap.val() === 0 || snap.val() === -1 || snap.val() == null){
            ref.child(this.uid).set(1);
          } else if (snap.val() === 1) {
          ref.child(this.uid).set(0);
          }
          else {
            console.log("Error in upvoting. snap.val(): " + snap.val())
          }

        })

    } else {
        console.log("Doesn't exist")
        ref.child(this.uid).set(1);
    }
});
}
else {
    console.log("Must be logged in to vote.")
}
}

如果我错过相关代码,请告诉我,我会提供相关代码。在投票结束后,我尝试调用componentDidMountthis.forceUpdate()(即使不鼓励)只是为了看看它是否是一个解决方案,它似乎并不是。

继承人在App.js中呈现的玩家组件

{
  orderedPlayersUp.map((player) => {
    return (
      <Player
        playerContent={player.playerContent}
        playerId={player.id}
        key={player.id}
        upvotePlayer={this.upvotePlayer}
        downvotePlayer={this.downvotePlayer}
        userLogIn={this.userLogIn}
        userLogOut={this.userLogOut}
        uid={this.uid}
      />
    )
  })
}

修改

当我将upvotePlayer函数的数据库调用更改为.on而非.once并继续upvote播放器时,它会从此componentWillMount函数中喷出无限量的console.logs :

App.js第51行是下面的console.log。

  this.database.on('child_changed', function (snapshot) {
    var name = snapshot.val();
    console.log("Player: " + name.playerContent + " has  " + name.votes + " votes.")
  })

在自身超载20秒左右后,出现错误页面并显示RangeError: Maximum call stack size exceeded

将componentWillMount函数数据库调用更改为this.database.once而不是.on会减少无限循环,但仍会抛出RangeError: Maximum call stack size exceeded

错误:
enter image description here
enter image description here

App.js(投票发生的地方(upvotePlayer))和Player.jsx的要点。 Gist with App.js and Player.jsx

EDIT2

当我在comondentDidMount()的Player.jsx文件中从.once更改为.on时,投票立即开始注册到屏幕,如下所示。为了澄清,这解决了我在投票图标从upvote变为downvote时实时没有变化的问题。我还没有测试是否注册一名球员超过另一名球员,而我的原始选票更多。只是想澄清任何可能通过这些代码来帮助自己的人。

componentDidMount() {
  let ref = firebase.database().ref('/players/' + this.playerId + '/voters');

  ref.on('value', snap => {
    var value = snap.val()

    if (value !== null && this.props.uid !== null) {       
        ref.child(this.props.uid).on('value', snap => {
          if (snap.val() === 1){
            this.setState({ votedUp: true, votedDown: false })
            }
          else if (snap.val() === 0) {
            this.setState({ votedUp: false, votedDown: false })
          }
          else if (snap.val() === -1) {
            this.setState({ votedDown: true, votedUp: false })
          }
          else {
          console.log("Error calculating the vote.")
          }
        })
    } else {
      //Error
    }
});

  }

1 个答案:

答案 0 :(得分:1)

您的firebase调用此时是.once()调用。这只会调用数据库一次。如果您希望组件继续侦听更改,则需要切换到.on()调用。因此,ref.child(this.uid).on(...)代替ref.child(this.uid).once(...)

ref.child(this.uid).on('value', snap => {
          if (snap.val() === 0 || snap.val() === -1 || snap.val() == null){
            ref.child(this.uid).set(1);
          } else if (snap.val() === 1) {
          ref.child(this.uid).set(0);
          }
          else {
            console.log("Error in upvoting. snap.val(): " + snap.val())
          }

        })