我正在开发一个以React为前端的MERN堆栈应用程序。这是一款依靠socketIO知道其他玩家何时移动的游戏,以便该游戏可以从数据库中进行REST API调用,以使React刷新游戏板。
它工作得很好,但是React应用偶尔似乎都不会收到socketIO消息,尽管据我所知,socketIO保证了传递。这是一个很难复制的错误。一个想法是,当消息到达时,React可能正在刷新,并且某种程度上搞砸了事情。因此,我添加了一个标志,该标志在消息到达时设置为true
,并在加载更新的游戏时清除该标志,并将其放入React state
中,从而引起(希望)刷新。奇怪的是,在标记仍为render
时正在调用true
。为什么会这样?
使用伪代码
this.state = game
updateFlag = false
onSocketMessage => {
updateFlag = true
asyncGetNewGame
.then(game => {
updateFlag = false
this.setState({game})
})
}
render() {
log.debug(updateFlag) // is true, but why?
const {state:{game}} = this
<SomeComponent game={game}>
}
如上所述,标记在渲染过程中仍为true
,但我认为在异步调用获取新游戏后,标记的同步设置为false
会发生在之前。 渲染,因为据我所知,渲染是由state
字段game
的更改引起的,直到更改标志后我才进行设置
我正确理解时间表吗?如果有人可以帮助阐明这一点,我将不胜感激。
答案 0 :(得分:2)
好吧,setState
不是同步方法,因此,以前对其的任何调用都可能触发渲染,而不一定是onSocketMessage
中的那个。此外,对组件道具的修改可能会导致重新渲染。如果您想为updateFlag
遵循同步逻辑,建议您使用回调:setState(value, callback)
。
另外,请注意here中的以下语句:
setState()将始终导致重新渲染,除非 shouldComponentUpdate()返回false。如果存在易变的物体 使用和条件渲染逻辑无法在 shouldComponentUpdate(),仅在新状态时调用setState() 与以前的状态有所不同,将避免不必要的重新渲染。
因此,如果您的逻辑取决于渲染,则可能是错误的,因为其他情况可能会触发重新渲染。是的,socket.io保证数据包/消息传递,但不能保证其他因素(例如逻辑,网络状态/配置)正常。如果出现问题,建议您使用套接字客户端和服务器检查错误事件。
此外,如果您的逻辑取决于特定状态/属性值的更改,则应使用componentDidUpdate进行验证。
希望我能帮上忙。