skip to Main Content

In my react app, I initialize a connection with the backend socket Io server. Inside the server, I console.log the socket that has connected, and everything works as expected, the client connects fine.

However, after connecting, the server emits an event, and on the client I am listening to this event, however the listener is not being fired.

Here is the client:

import io from "socket.io-client"

const socket = io.connect("http://localhost:5000")

const Home = () => {
    const [welcome, setWelcome] = useState("")

    useEffect(() => {
        socket.on("welcome", (data) => {
            // This code here never gets executed
            console.log("hit")
            setWelcome(data)
        })

        return () => socket.off("welcome")
    }, [socket])

    return (
        <>
            {welcome}
        </>
    )

And here is the server code for the socket:

const io = new Server(httpServer, {
    cors: {
        origin: "http://localhost:3000",
        methods: ["GET", "POST"]
    },
})

io.on("connection", (socket) => {
    socket.emit("welcome", "Hello")
    // The console log logs the socket id as expected
    console.log(`User connected: ${socket.id}`)
})

I would like to add that the code inside socket.on(welcome) does get executed one time when the page first loads, however after a page refresh, the code never gets executed. The server still logs a new connection after a page refresh, however the on("welcome") listener doesn’t get fired.

Why is the react code not firing the socket listener? Thanks.

2

Answers


  1. I can’t comment because I lack of reputation. Does the previous connection closes on page refresh? (because it should). On server side, you could check with something like

    socket.on("disconnect", () => { console.log(`User disconnected: ${socket.id}`) })
    

    However, the issue is in the frontend, because you say that a new connection is logged when page refresh is performed. You could try to debug your useEffect to see if the socket instance is actually being created with console.log(socket):

    useEffect(() => {
        // Debug
        console.log(socket)
        socket.on("welcome", (data) => {
            // This code here never gets executed
            console.log("hit")
            setWelcome(data)
        })
    
        return () => socket.off("welcome")
    }, [socket])
    

    The only reason you aren’t receiving the event on client side is because there isn’t a listener, so your socket instance is the issue. It seems that the useEffect cleanup is executed and the event listener is removed and never created again.

    By the way, if you are building a websocket-based app, there isn’t a problem if you connect the socket on page load or component mount. But if your app will use sockets only on certain sections, you should create the socket instance and then connect and disconnect when your app needs to.

    Login or Signup to reply.
  2. @Herb adams – I suspect you are not running your local on port 3000. Two, the way you try to use socket as dependency is not correct in your client code. React doesnt rerender when there is mutation on variable declared ouside component. And three the return callback to socket off is bad code, check this link 1 remarks about cleanup in useEffect

    Note – with my below code server is running port 3000 and client running on port 3001

    server code:

    const path = require("path");
    const http = require("node:http");
    const Server = require('socket.io')
    const cors = require('cors');
    const express = require("express");
    const app = express();
    const httpServer = http.createServer(app);
    
    const port = 3000;
    const publicDirectoryPath = path.join(__dirname, "../public");
    
    app.use(express.static(publicDirectoryPath));
    app.options('*', cors())
    
    
    const io =  Server( httpServer, {
     cors: {
         origin: "http://localhost:3001",
         methods: ["GET", "POST"]
         },
      })
    
     io.on("connection", (socket) => {
       socket.emit("welcome", "Hello")
    
       console.log(`User connected: ${socket.id}`)
     })
    
     httpServer.listen(port, () => {
        console.log(`Server is up on port ${port}!`);
      });
    

    **client code: **

    link 2- how to use socket.io in react

    import { io } from "socket.io-client";
    import {useEffect, useState} from 'react'
    
    const URL = "http://localhost:3000/";
    const socket = io(URL);
    
    function App() {
    
      const [isConnected, setIsConnected] = useState(socket.connected);
      const [welcome, setWelcome] = useState("")
    
      /*  this below first useEffect code is commented, but this is correct way to 
    listen on a socket event and disconnect on a socket. please check above link 2.
         
         
         useEffect(() => {
             function onConnect(data) {
              console.log("on connect --set data that came from server..");
             setWelcome(data)
          }   
         // socket.on("connect", onConnect);         
          socket.on("welcome", onConnect);    
    
         return () => socket.off("welcome", onConnect);
         }, []) */
    
    
        useEffect(() => {
           socket.on("welcome", (data) => {
              // This code here never gets executed
              console.log("hit")
              setWelcome(data)
          })
    
          return () => socket.off("welcome")
       }, [socket]) // the dependency is bad. see below image.
    
      return (
            <>
                {welcome}
            </>)
      }
    
     export default App;
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search