与 Socket.io 反应 - 在“socket.on”事件上不断地重新渲染

Posted

技术标签:

【中文标题】与 Socket.io 反应 - 在“socket.on”事件上不断地重新渲染【英文标题】:React with Socket.io - continously re-render on "socket.on" event 【发布时间】:2018-07-27 21:17:03 【问题描述】:

我正在尝试编写一个客户端,它打开与服务器的 socket.io 连接,然后使用从服务器通过套接字发送的更新数字不断地重新渲染屏幕。我无法获取要更新的号码。 “速度”值保持在 10。有什么问题? - 显然是我理解的一个非常基本的错误。谢谢!

客户端代码:

  import React from 'react';
    import CircleGauge from 'react-launch-gauge';
    import io from 'socket.io-client';


    class App extends React.Component 
        constructor(props, context) 
            super(props, context)
            this.state = 
                speed: 10
            ;
        
        componentDidMount() 
            const socket = io.connect('http://localhost:5000');
            socket.on( 'data update', data => this.setState(speed: data));
            console.log("got the speed: " + this.state.speed);
        

        render() 
            return (
                <div>
                    <p> The velocity received is: this.state.speed  </p>
                </div>
            );
        
    
    export default App;

服务器代码:

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import time

sendData = False;

app = Flask(__name__)
socketio = SocketIO(app)

@socketio.on('connect')
def dataSent():
    print('they connected*************')
    for i in range(20,100):
        emit('data update', i)
        time.sleep(1)
        print(i)


if __name__ == '__main__':
    socketio.run(app, debug = True)

【问题讨论】:

【参考方案1】:

在下面检查我的工作代码:

import React,  useEffect, useState, useRef  from 'react'
import socket from 'socket.io-client'

const Chatbox = () => 
  const [chats, setChats] = useState([])
  const [message, setMessage] = useState('')
  const socketClientRef = useRef()

  useEffect(() => 
    const client = socket("http://localhost:3002");
    client.on("connect", () => 
      console.log('connected')
    )
    client.on("disconnect", () => 
      console.log('diconnected')
    );
    client.on("chat", message => 
      setChats(prevChats => [...prevChats, message])
      // INSTEAD OF:
      // setChats([...chats, message])
    );
    socketClientRef.current = client
    return () => 
      client.removeAllListeners()
    
  , [])

  const handleSend = async () => 
    socketClientRef.current.emit('chat', 
      room: `event-$eventId`,
      message
    )
    setMessage('')
  


  return (
    <div>
      <div>
        <h1>Messages</h1>
        chats.map(chat => (
          <div>chat</div>
        ))
      </div>
      <div>
        <input value=message onChange=e => setMessage(e.target.value) />
        <button onClick=handleSend>Send</button>
      </div>
    </div>
  )

【讨论】:

【参考方案2】:

您已经接近了,但是您在客户端上设置套接字的方式存在一些小问题。

首先,您设置的套接字与文档建议的略有不同。

componentDidMount() 
  // io() not io.connect()
  this.socket = io('http://localhost:5000');

  this.socket.on(
    // consider renaming this to 'data_update' or just 'update'
    'data update', 
    data => 
      this.setState(
         speed: data ,
        // the second parameter to setState will be called on completion, so you'll log every time the speed changes
        () => console.log("got the speed: " + this.state.speed)
      )
  );

  this.socket.open();

最后,您需要在卸载组件时关闭套接字:

componentWillUnmount() 
  this.socket.close();

【讨论】:

感谢卢克的回答,但并没有解决问题。由于某种原因,控制台没有显示任何输出(并且速度不会改变),直到服务器发送最终值 99。此时,所有 80 条日志都打印出来,速度更新为 99

以上是关于与 Socket.io 反应 - 在“socket.on”事件上不断地重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

在 useEffect 中对 Socket.io 的第一个请求做出反应

如何将反应上下文与反应导航一起使用

Socket.io-client 未连接到 socket.io 服务器反应和节点(快递)

反应的socket.io聊天问题

socket.io 客户端在本机反应中接收对同一事件的多个调用

接收错误:xhr 轮询错误 socket.io 客户端反应