1

I'm a newbie to Socket.IO, I did the chat tutorial of the docs and the "homework" of the chat app to understand how it works, now I'm trying to connect an NodeJS server and a React App with a Socket. I've spent all day trying to do this, but I'm getting this error:

GET http://localhost:4000/?EIO=4&transport=polling&t=NYW26Ea 404 (Not Found)

The itention of my app is show an update of time, I'm using socket to update time on screen each one second. Here's my Server.js file, and yes, it is pretty simple:

const express = require("express")
const http = require("http")
const socketIO = require("socket.io")
var cors = require('cors')

const PORT = 4000;
const routes = require("./routes/index")

const app = express()
app.use(cors())
app.use(routes)

const server = http.createServer(app)

const io = socketIO(server)

let interval

io.on("connection", (socket) => {
    console.log("New client connected!")
    if(interval) {
        clearInterval(interval)
    }
    interval = setInterval(() => getApiAndEmit(socket), 1000)
    socket.on("disconnect", () => {
        console.log("Client is disconnected")
        clearInterval(interval)
    })
})

const getApiAndEmit = socket => {
    const response = new Date()
    socket.emit("from-api", response)
}

app.listen(PORT, () => console.log(`Application up and running on ${PORT}`))

If I visit the route I created with express it works fine.

And here is my App.js file:

import React, { useState, useEffect } from "react";
import socketIOClient from "socket.io-client";
const ENDPOINT = "http://127.0.0.1:4000";

function App() {
  const [response, setResponse] = useState("");

  useEffect(() => {
    const socket = socketIOClient(ENDPOINT);
    socket.on("from-api", data => {
      setResponse(data);
    });
  }, []);

  return (
    <p>
      It's <time dateTime={response}>{response}</time>
    </p>
  );
}

export default App;

Should I create a route for SocketIO or what?

Bruno
  • 25
  • 4

2 Answers2

1

Should I create a route for SocketIO or what?

No. When you do this:

const io = socketIO(server)

The socket.io library already installed its own route handler for routes starting with /socket.io and any other routes it needs. You don't need to do that yourself.

You do, however, have a problem because you're hooking up socket.io to server that you never started.

When you do this:

app.listen(PORT, () => console.log(`Application up and running on ${PORT}`))

That creates a new http server and then calls .listen() on it and returns that new server. You will need to capture that server and hook up socket.io to it:

So, replace this:

const server = http.createServer(app)

const io = socketIO(server)

app.listen(PORT, () => console.log(`Application up and running on ${PORT}`))

With this:

const server = app.listen(PORT, () => console.log(`Application up and running on ${PORT}`))
const io = socketIO(server);

Then, you're creating and starting just one http server and hooking up both Express and socket.io to it. They can both share the same http server on the same port. Socket.io will use the route prefix /socket.io to distinguish its own routes and once a given socket.io connection has been established, that specific connection switches protocol to the webSocket protocol (with socket.io data frame on top of it) and is no longer using http any more.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Great explanation. I did what you said and on the client react app I added this line: const socket = openSocket(ENDPOINT, { transports: ['websocket'] }); Now it works fine and communicate with the NodeJS socket server! – Bruno Apr 05 '21 at 16:37
  • @Bruno - Glad that worked! If this answered your question, then you can indicate that to the community by clicking the checkmark to the left of the answer. That will also earn you some reputation points for following the proper procedure here. – jfriend00 Apr 05 '21 at 20:23
1

Instead of:

app.listen(PORT, () => console.log(`Application up and running on ${PORT}`))

Use this:

server.listen(PORT, () => console.log(`Application up and running on ${PORT}`))

Reason: The server instance you are assigning to socketIO is not the same as the instance of server you are listening to.

With express you can pass the server instance like this:

var express   = require('express');
var app       = express();
...
...
...
var server    = app.listen(PORT);
var io        = require('socket.io').listen(server);

io.sockets.on('connection', function (socket) {
  ...
});

You can refer this: Express.js - app.listen vs server.listen

Abhishek Pankar
  • 723
  • 8
  • 26