Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React with Socket.io - continously re-render on "socket.on" event

I'm trying to write a client that opens a socket.io connection with a server and then continuously re-renders the screen with an updated number that is sent from the server through the socket. I can't get the number to update. The "speed" value stays at 10. What's the issue? - clearly a very basic error in my understanding. Thanks!

The client code:

  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;

The server code:

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)
like image 628
user3059217 Avatar asked Aug 11 '26 21:08

user3059217


2 Answers

Check my working code below:

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>
  )
}
like image 174
Muhammad Irvan Hermawan Avatar answered Aug 14 '26 09:08

Muhammad Irvan Hermawan


You're close, but there are a couple minor issues with the way you're setting up your socket on the client.

First, you were setting up the socket a little differently than the docs suggest.

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();
}

Finally, you'll want to close the socket when your component unmounts:

componentWillUnmount() {
  this.socket.close();
}
like image 32
Luke Willis Avatar answered Aug 14 '26 09:08

Luke Willis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!