简体   繁体   English

React何时准确渲染-在各种异步调用,socketIO和React之间管理状态的问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM