[英]When exactly does React render — problem managing state between various async calls, socketIO and React
I'm working on a MERN stack application with React as the front end. 我正在使用React作为前端的MERN堆栈应用程序。 It's a game that relies on socketIO to know when the other player has moved so that the game can do a REST API call from the DB to allow React to refresh the gameboard.
这是一款依靠socketIO来知道其他玩家何时移动的游戏,以便该游戏可以从数据库执行REST API调用,以允许React刷新游戏板。
It works pretty well, but every once in a while the React app doesn't seem to receive the socketIO message, although, as I understand it, socketIO guarantees delivery. 它工作得很好,但是React应用偶尔似乎都不会收到socketIO消息,尽管据我所知,socketIO保证了交付。 It's a hard bug to reproduce.
这是一个很难复制的错误。 One idea was that React might be doing a refresh when the message arrived and that somehow screwed things up.
一个想法是,当消息到达时,React可能正在刷新,并且某种程度上搞砸了事情。 So I added a flag which I set to
true
when the message arrives, and clear the flag when the updated game is loaded, which I put into the React state
, causing (I hope) a refresh. 因此,我添加了一个标志,该标志在消息到达时设置为
true
,并在加载更新的游戏时清除该标志,并将其置于React state
,从而(希望)刷新。 The weird thing is that render
is being called while the flag is still true
. 奇怪的是,当标志仍然为
true
时,正在调用render
。 Why is that? 这是为什么?
In pseudocode 用伪代码
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}>
}
As per above, the flag remains true
during the render, but I would think the synchronous setting of the flag to false
after the async call to fetch the new game would happen before the render, because the render, as I understand it, is being caused by the change to the state
field game
, which I don't set until after I've changed the flag. 如上所述,该标志在渲染期间保持为
true
,但我认为在异步调用下获取新游戏后,将标志的同步设置设置为false
会在渲染之前进行,因为据我所知,由state
字段game
的更改引起的,直到更改标志后才设置。
Am I understanding the timeline correctly? 我是否正确理解时间表? If anyone could help shed some light on this I'd appreciate it.
如果有人可以帮助阐明这一点,我将不胜感激。
Well, setState
is NOT a synchronous method, so, any previous call to it might be triggering the render, not necessarily the one in onSocketMessage
. 好吧,
setState
不是同步方法,因此,以前对其的任何调用都可能会触发呈现,而不一定是onSocketMessage
中的onSocketMessage
。 Also, a modification to the component props might cause a re-render. 此外,对组件道具的修改可能会导致重新渲染。 If you want to follow a synchronous logic for
updateFlag
I suggest you using a callback: setState(value, callback)
. 如果要为
updateFlag
遵循同步逻辑,建议您使用回调: setState(value, callback)
。
Also, notice this statement from here : 另外,还要注意从这句话在这里 :
setState() will always lead to a re-render unless shouldComponentUpdate() returns false.
除非shouldComponentUpdate()返回false,否则setState()将始终导致重新渲染。 If mutable objects are being used and conditional rendering logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.
如果正在使用可变对象,并且不能在shouldComponentUpdate()中实现条件渲染逻辑,则仅当新状态不同于先前状态时调用setState()才能避免不必要的重新渲染。
So, if your logic depends on renders, then, it might be wrong as other things could trigger a re-render. 因此,如果您的逻辑依赖于渲染,则可能是错误的,因为其他情况可能会触发重新渲染。 And yes, socket.io guarantees packets/messages deliveries, but it does not guarantee other factors such as your logic, network status/configuration are fine.
是的,socket.io保证数据包/消息传递,但不能保证其他因素(例如逻辑,网络状态/配置)正常。 I suggest you to check out in the error events with your socket client and server if something has gone wrong.
如果出现问题,建议您使用套接字客户端和服务器检查错误事件。
Also, if your logic depends on specific state/props value changes, then you should use componentDidUpdate for validations. 另外,如果您的逻辑取决于特定状态/属性值的更改,则应使用componentDidUpdate进行验证。
Hope I could help. 希望我能帮上忙。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.