1

On the client side, it calls socket.current.emit in useEffect. I am trying to send the name and age to the server and display the data in the server side io.on terminal. I have no error, nothing is displayed in the terminal.

BACKEND

server.js

const express = require('express');
require('dotenv').config();

const app = express();
const port = process.env.PORT || 8000;

const server = app.listen(port, () => {
    console.log(`connect on the port ${port} - ${process.env.NODE_ENV}`);
});

const io = require('socket.io').listen(server);


io.on('connection', socket => {
    socket.on('hello', data => {
      console.log({name: data.name, age: data.age});
    });
});

FRONTEND

client

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


const ChatUser = () => {

    const [values, setValues] = useState({
        chatters: [],
        idReceiver: '',
        idSender: ''
    });

    const [activeUser, setActiveUser] = useState('');
    const [message, setMessage] = useState('');
    const [chats, setChats] = useState([]);

    const socket = useRef();
    

    useEffect(() => {

        if(!socket.current) {
            socket.current = io(process.env.REACT_APP_API);
        }

        if(socket.current) {
            socket.current.emit('hello', {name: 'john', age: '23'});
        }
    }, []);


    return (
        <>  

        </>
    );
};

//env
REACT_APP_API=http://localhost:8000/api

Updated backend

My code in server.js Maybe I should put io.on in different place?

const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const db = require('./connection');
const app = express();


// Connect to our Database and handle an bad connections
mongoose
    .connect(process.env.DATABASE, { 
        autoIndex: false
    })
    .then(() => console.log("DB server connect"))
    .catch(() => console.log("DB server disconnect"))


const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/user');
const messageRoutes = require('./routes/message');
const countriesRoutes = require('./routes/countries');
const languagesRoutes = require('./routes/languages');
const tutorRoutes = require('./routes/tutor');

app.use(morgan('dev'));
app.use(bodyParser.json({limit: '50mb'}));

app.use((req,res,next)=>{
    res.header('Content-Type: application/json');
    res.header('Access-Control-Allow-Origin','*'); 
    res.header('Access-Control-Allow-Headers','Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Access-Control-Allow-Request-Method');
    res.header('Access-Control-Allow-Methods','GET, PUT, POST, DELETE, OPTIONS');
    res.header('Allow','GET, PUT, POST, DELETE, OPTIONS');

    req.io = io;
    next();
});

if(process.env.NODE_ENV === 'development') {

    app.use(cors());

}

const port = process.env.PORT || 8000;

const server = app.listen(port, () => {
    console.log(`connect on the port ${port} - ${process.env.NODE_ENV}`);
});


const io = require('socket.io').listen(server, {
  cors: {
    origin: '*'
  }
});


io.on('connection', socket => {
    socket.on('hello', data => {
      console.log({name: data.name, age: data.age});
    });
});


//middleware
app.use('/api', authRoutes);
app.use('/api', userRoutes);
app.use('/api', countriesRoutes);
app.use('/api', languagesRoutes);
app.use('/api', tutorRoutes);
app.use('/api', messageRoutes);

Request header

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Host: localhost:8000
Origin: http://localhost:3000
Referer: http://localhost:3000/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36

404 not found - in terminal

GET /socket.io/?EIO=4&transport=polling&t=NtFERz- 404

Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Umbro
  • 1,984
  • 12
  • 40
  • 99
  • Are you sure there are no errors on browser console? I tested you code and I see CORS error on browser. If you can confirm that you are also getting this error on browser then this answer should help. https://stackoverflow.com/a/38749535/6338245 – Fahad Farooq May 04 '21 at 20:38
  • @FahadFarooq I added my full code in file server.js. Maybe I should put `io.on` in different place or change order functions? – Umbro May 06 '21 at 21:12
  • when I run you backend code I get `TypeError: require(...).listen is not a function` on line: `const io = require("socket.io").listen(server, {`. Which version of `socket.io` are you using? – Fahad Farooq May 06 '21 at 21:19
  • NVM, The problem here is that you are trying to connect to the wrong url. – Fahad Farooq May 06 '21 at 21:45
  • @FahadFarooq "socket.io-client": "^3.0.5", – Umbro May 06 '21 at 22:46

3 Answers3

1

You did not combine the express and socket correctly to set up the server.

Also you can see this video:

React and Socket.io with Express in 15 minutes

SERVER - BACK-END

Follow the steps below:

  1. The Built-in HTTP Module
    • Node.js has a built-in module called HTTP, which allows Node.js to transfer data over the Hyper Text Transfer Protocol (HTTP). The HTTP module can create an HTTP server that listens to server ports and gives a response back to the client.
    • Use the createServer() method to create an HTTP server:
const http = require("http");
const express = require("express");
const app = express();

const server = http.createServer(app);
  1. Create a utility file with a custom name, here is the name of this socketUtils.js :
    • Here we set up the socket with custom configs, and instantiate.
// <root-project-dir>/utils/socketUtils.js

const socketIO = require("socket.io");

exports.sio = (server) => {
  return socketIO(server, {
    transports: ["polling"],
    cors: {
      origin: "*",
    },
  });
};

exports.connection = (io) => {
  io.on("connection", (socket) => {
    console.log("A user is connected");

    socket.on("message", (message) => {
      console.log(`message from ${socket.id} : ${message}`);
    });

    socket.on("disconnect", () => {
      console.log(`socket ${socket.id} disconnected`);
    });
  });
};
  1. Well now it's time to use the socketUtils.js file:
const http = require("http");
const dotenv = require("dotenv");
const cors = require("cors");

dotenv.config({
  path: "./config.env",
});

const express = require("express");
const app = express();
const socketUtils = require("./utils/socketUtils");

const server = http.createServer(app);
const io = socketUtils.sio(server);
socketUtils.connection(io);
  1. Create a socket middleware:
    • To access the socket globally in each request, we create a middleware.
const socketIOMiddleware = (req, res, next) => {
  req.io = io;

  next();
};
  1. Use the listen() method:
    • You can write other middleware according to the priority that exists with the routes you need and then put the listen() method at the end.
// CORS
app.use(cors());

// ROUTES
app.use("/api/v1/hello", socketIOMiddleware, (req, res) => {
  req.io.emit("message", `Hello, ${req.originalUrl}`);
  res.send("hello world!");
});

// LISTEN
const port = process.env.PORT || 8000;
server.listen(port, () => {
  console.log(`App running on port ${port}...`);
});

The final file should look like this:

// <root-project-dir>/index.js

const http = require("http");
const dotenv = require("dotenv");
const cors = require("cors");

dotenv.config({
  path: "./config.env",
});

const express = require("express");
const app = express();
const socketUtils = require("./utils/socketUtils");

const server = http.createServer(app);
const io = socketUtils.sio(server);
socketUtils.connection(io);

const socketIOMiddleware = (req, res, next) => {
  req.io = io;

  next();
};

// CORS
app.use(cors());

// ROUTES
app.use("/api/v1/hello", socketIOMiddleware, (req, res) => {
  req.io.emit("message", `Hello, ${req.originalUrl}`);
  res.send("hello world!");
});

// LISTEN
const port = process.env.PORT || 8000;
server.listen(port, () => {
  console.log(`App running on port ${port}...`);
});

Finally, to test the server, you can use SocketIO Client Tool online tool, which is very useful.


CLIENT - FRONT-END

After setting up the server, you can use it as follows in the React app and emit an event:

import { useEffect, useRef } from "react";
import "./App.css";

import { io } from "socket.io-client";

function App() {
  const socket = useRef();

  useEffect(() => {
    socket.current = io("ws://localhost:9013");

    socket.current.on("connnection", () => {
      console.log("connected to server");
    });
  }, []);

  const handleClick = () => {
    socket.current.emit("message", new Date().getTime());
  };

  return (
    <div className="App">
      <p>Socket.io app</p>

      <button type="button" onClick={handleClick}>
        Emit a time message
      </button>
    </div>
  );
}

export default App;

Finally, you can access the source code in GitHub repo via the link below: https://github.com/mohammadoftadeh/simple-react-socket-io

Mohammad Oftadeh
  • 1,410
  • 1
  • 4
  • 11
  • It doesn't work form me. I see in tab " network" in dev tools browser "Request URL: http://localhost:8900/socket.io/?EIO=4&transport=polling&t=Ntie-9O " it is red color – Umbro Dec 24 '21 at 13:33
  • @Umbro. It's work correctly, You definitely did some parts wrong, because it has been tested and everything works perfectly in the video tutorial I linked to. https://youtu.be/SMubOngCCmw – Mohammad Oftadeh Dec 24 '21 at 14:10
  • Can you put your code on https://stackblitz.com/. Online code editor? – Umbro Dec 25 '21 at 12:58
  • @Umbro. You can access the source code in GitHub repo via the link below: https://github.com/mohammadoftadeh/simple-react-socket-io – Mohammad Oftadeh Dec 25 '21 at 16:54
  • But your file `client` in Github isn't configurate – Umbro Dec 25 '21 at 17:01
  • @Umbro. I added the client in GitHub. You can check again. Everything is working great, Sorry, I do not know why I think you are looking for an excuse. https://github.com/mohammadoftadeh/simple-react-socket-io/tree/main/react-client – Mohammad Oftadeh Dec 25 '21 at 19:09
0

Change REACT_APP_API env variable from http://localhost:8000/api to http://localhost:8000 i.e. remove the /api.

Fahad Farooq
  • 449
  • 5
  • 11
  • It doesn't work. I run app in browser using url: http://localhost:3000, server port 8000.. Maybe my variable in `env` I should change to; REACT_APP_API env variable from http://localhost:3000 ?? – Umbro May 06 '21 at 22:46
  • I have your code running on my system without any problem after this change, though I am on socket-io version 4. I'll check on your version. Meanwhile, can you attach a SS of your request headers from network tab. Request headers for any one of the requests that start with `/socket.io/?`. – Fahad Farooq May 06 '21 at 23:03
  • Same with your version, no issues. Can you attach a Screen Shot of your network request. That will give me some clue about the issue. – Fahad Farooq May 06 '21 at 23:11
  • Can you try changing `socket.current = io(process.env.REACT_APP_API);` to `socket.current = io("http://localhost:8000");`. – Fahad Farooq May 06 '21 at 23:56
  • Updated. I added request header – Umbro May 08 '21 at 07:40
0

Use the http package.

const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);

io.on('connection', socket => {
    ....
});

server.listen(3000, () => {
    ....
});
Neobyte
  • 386
  • 3
  • 10
  • I did it, but i can't still see result in terminal – Umbro May 07 '21 at 09:01
  • If you console.log just before the "socket.on" line, do you get a confirmed connection? – Neobyte May 07 '21 at 10:38
  • I did in this way: `io.on('connection', function(data) { console.log('new client connected'); });` and I can see 'new client connected` in my terminal – Umbro May 07 '21 at 11:00
  • Yes, I can see `console.log('new client connected');` before `socket.on` – Umbro May 07 '21 at 11:02