Socket.io Emit data on GET request using Reactjs & Expressjs - node.js

I am using socket.io to send real-time data from Express Server to Reactjs Client, but the data will be sent only on get request from React client.
The code works perfectly, but when I add routing to Express server and fetch method in client side, it does not work.
server side (server.js) :
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const axios = require("axios");
const PORT = process.env.PORT || 8001;
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
app.get('/system/overview',(req,res) => {
io.on("connection", socket => {
console.log("New client connected"), setInterval(
() => getAndEmitData(socket),
1000
);
socket.on("disconnect", () => console.log("Client disconnected"));
});
const getAndEmitData = async socket => {
try {
const response = await axios.get(
"https://api.darksky.net/forecast/927aa7bef57ca7b2422"
);
socket.emit("temp", response.data.currently.temperature);
} catch (error) {
console.error(`Error: ${error.code}`);
}
};
})
server.listen(PORT, () => console.log(`Listening on port ${PORT} ...`));
client side ( Overview.js Component ) :
import socketIOClient from "socket.io-client";
...
class Overview extends Component {
constructor() {
super();
this.state = {
response: false,
endpoint: "http://localhost:8001"
};
}
componentDidMount() {
const { dispatch } = this.props;
const { endpoint } = this.state;
dispatch({
type: 'profile/fetchAdvanced',
});
const socket = socketIOClient(endpoint);
fetch('http://localhost:8001/system/overview', {
method: 'get',
})
.then(res => res.json())
.then(data => {
socket.on("temp", data => this.setState({ response: data }));
})
}
...
There is no error but the server does not handle GET request from react client when ComponentDidMount function was executed!
What is the best way to do that ?
Thanks...

Related

Socket.io server not runnning

i'm developing a chat app in express by socket.io and this is my code:
well the front end cannot connect to socket io but server is running and i can login
const express = require("express");
const { Server } = require("socket.io");
const helmet = require("helmet");
const cors = require("cors");
const authRouter = require("./routes/authRouter");
const { corsConfig } = require("./controllers/serverController");
const {
Authorization,
AddFriend,
Disconnect,
dm,
} = require("./controllers/socketController");
require("dotenv").config();
const app = express();
const server = require("http").createServer(app);
const io = new Server(server, {
cors: corsConfig,
});
app.use(helmet());
app.use(cors(corsConfig));
app.use(express.json());
//! Routes
app.use("/auth", authRouter);
app.get("/", (req, res) => res.send("Hi"));
io.use(Authorization);
io.on("connection", (socket) => {
console.log("socket")
socket.on("add_friend", (friendName, cb) => {
AddFriend(socket, friendName, cb);
});
socket.on("disconnect", Disconnect);
socket.on("dm", (message) => dm(socket, message));
});
server.listen(5050, () => {
console.log(app.get("env"));
});
but my server isnt running on localhost:5050 this is the error i got :
curl "http://localhost:5050/socket.io/?EIO=4&transport=polling" curl: (7) Failed to connect to localhost port 5050: Connection refused
ive tried to change config of socket server but none of those worked
i have a socketjs file which will create my config and a useEffect hook which inside that ive tried to connect to my server
frontendCode:
socket.js
import { io } from "socket.io-client";
const socket = (user) =>
new io("http://localhost:5050", {
autoConnect: false,
withCredentials: true,
auth: {
token: user.token,
},
});
export default socket;
useSocket.js:
socket.connect();
socket.on("friends", (FriendList) => {
setFriendList(FriendList);
});
socket.on("messages", (messages) => {
setMessages(messages);
});
socket.on("dm", (message) => {
setMessages((prev) => [message, ...prev]);
});
socket.on("connected", (status, username) => {
setFriendList((prev) => {
const friends = [...prev];
return friends.map((friend) => {
if (friend.username === username) {
friend.status = status;
}
return friend;
});
});
});
socket.on("connect_error", () => {
setUser({ loggedIn: false });
});
returned error from frontend:
Firefox can’t establish a connection to the server at ws://localhost:5050/socket.io/?EIO=4&transport=websocket&sid=1uKM4znamAHH8P6kAAKY.

cannot connect react to socket io server

I wrote a simple hook to connect react and socket.io:
import io from 'socket.io-client'
import { useEffect, useRef } from 'react'
import { v1 as uuid } from 'uuid';
import { useParams } from "react-router-dom";
const SERVER_URL = 'http://localhost:3001'
export const useSocketConnection = () => {
const { gameId } = useParams()
const userId = uuid()
const socketRef = useRef()
useEffect(() => {
console.log('connectSocket')
socketRef.current = io(SERVER_URL, {
query: { gameId }
})
socketRef.current.emit('join-room', {
userId
})
return () => {
console.log('disconnectSocket')
socketRef.current.disconnect()
}
}, [gameId])
}
the server code is pretty simple:
const express = require("express");
const http = require("http");
const app = express();
const server = http.createServer(app);
const socket = require("socket.io");
const io = socket(server);
const cors = require('cors');
app.use(cors({credentials: true, origin: 'http://localhost:3000'}));
app.get('/', (req, res) => {
res.send('This endpoint works pretty fine')
})
io.on('connection', socket => {
console.log('connected user', socket.id, new Date()) //this log works
socket.on('join-room', () => {
console.log('hope this will work') //doesn't work at all
})
});
server.listen(3001, () => console.log('server is running on port 3001'));
when component renders useEffect hook hires just one time(look screen below)
But server gets one more connection every 5 or 6 seconds I don't know why. If look to the image below each connection has new id and the period of adding new connections is 6 seconds. Also socket.on('join room') doesnt work at all :(
Please help to figure out what Im doing wrong, couldn't find nothing helpful in the internet 🥺🥺🥺.Thank you in advance <3

Socket.io-client is not connecting to socket.io server react and node(express)

I try to connect to a socket.io-client using the following code:
client:
import queryString from 'query-string';
import React, { useEffect, useState } from 'react';
import io from 'socket.io-client';
let socket;
const Chat = ({location}) => {
const [name, setName] = useState("");
const [room, setRoom] = useState("");
const EP = 'http://localhost:5000/';
useEffect(() =>{
const {name , room} = queryString.parse(location.search);
socket = io(EP);
setName(name);
setRoom(room);
console.log(socket);
},[EP, location.search])
return(
<h1>helloooooooooooooo {name} welcome to {room}</h1>
)
}
export default Chat;
server:
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const router = require('./router/router');
const PORT = process.env.PORT ||5050;
const app = express();
const server = http.createServer(app);
const io = socketio(server);
//socket.io
io.on('connection', socket => {
console.log("we have a new user!!!!!!!!!");
socket.on('disconnect', () =>{
console.log('User had left!');
})
})
// io.on('connection', socket => {
// console.log("we have a new user!!!!!!!!");
// socket.on("disconnect", () => console.log("user is left"))
// });
app.use(router);
server.listen(PORT, () => console.log(`Server has started on ${PORT}`));
i dont get connet or disconnect console log from this server socket.
i follow same process as socke.io doc.
console message from browser, its showing disconnected true and connected false and no id
Since Socket.IO v3, you need to explicitly enable Cross-Origin Resource Sharing (CORS).
https://socket.io/docs/v3/handling-cors/
// server-side
const io = require("socket.io")(httpServer, {
cors: {
origin: "https://example.com",
methods: ["GET", "POST"],
allowedHeaders: ["my-custom-header"],
credentials: true
}
});
// client-side
const io = require("socket.io-client");
const socket = io("https://api.example.com", {
withCredentials: true,
extraHeaders: {
"my-custom-header": "abcd"
}
});
in client, inside useEffect instead of
socket = io(EP);
to this
socket = io.connect(EP , {
"force new connection" : true,
"reconnectionAttempts": "Infinity",
"timeout" : 10000,
"transports" : ["websocket"],
withCredentials:true,
extraHeaders:{
"my-custom-header": "abcd"
}
});
i got this solution from this question
In the browser, the WebSocket object does not support additional headers. In case you want to add some headers as part of some authentication mechanism, you can use the transportOptions attribute. Please note that in this case the headers won't be sent in the WebSocket upgrade request.
// WILL NOT WORK in the browser
const socket = new Socket('http://localhost', {
extraHeaders: {
'X-Custom-Header-For-My-Project': 'will not be sent'
}
});
// WILL NOT WORK
const socket = new Socket('http://localhost', {
transports: ['websocket'], // polling is disabled
transportOptions: {
polling: {
extraHeaders: {
'X-Custom-Header-For-My-Project': 'will not be sent'
}
}
}
});
// WILL WORK
const socket = new Socket('http://localhost', {
transports: ['polling', 'websocket'],
transportOptions: {
polling: {
extraHeaders: {
'X-Custom-Header-For-My-Project': 'will be used'
}
}
}
});
Credit: Engine.IO client

Can't get React + socket.io to work on Heroku

I'm trying to set up a simple socket.io echo server on Heroku using Express and React. The server returns the React site from the build folder, then listens for incoming messages using onAny(). Everything works fine locally, but when deployed to Heroku none of the client-emitted messages are going through after the connection has been established.
I've used Heroku's guide as well as create-react-app and this Medium article as my starting points, and did make sure to turn on http-session-affinity as the Heroku guide said to.
Currently, the React client is set up to emit a fixed message through the onclick handler of a <span>.
Here's the contents of server.js:
'use strict';
const path = require('path');
const express = require('express');
const socketIO = require('socket.io');
const PORT = process.env.PORT || 3000;
const app = express()
.use(express.static('build'))
.listen(PORT, () => console.log(`Listening on ${PORT}`));
const io = socketIO(app);
io.on('connection', (socket) => {
console.log('Client connected');
socket.on('disconnect', () => console.log('Client disconnected'));
socket.onAny((type, data) => {
console.log('Received:');
console.log(data);
socket.emit('echo', data);
});
});
And here is the client-side React hook that establishes the connection and emits the messages, where I replace [app-name] with the Heroku app name:
import { useEffect, useRef, useState } from "react";
import socketIOClient from "socket.io-client";
const NEW_CHAT_MESSAGE_EVENT = "newChatMessage";
// const SOCKET_SERVER_URL = 'localhost:3000';
const SOCKET_SERVER_URL = 'wss://[app-name].herokuapp.com/sockjs-node';
const useChat = (roomId) => {
const [messages, setMessages] = useState([]);
const socketRef = useRef();
useEffect(() => {
socketRef.current = socketIOClient(SOCKET_SERVER_URL, {
query: { roomId },
});
socketRef.current.on(NEW_CHAT_MESSAGE_EVENT, (message) => {
console.log(message);
const incomingMessage = {
...message,
ownedByCurrentUser: message.senderId === socketRef.current.id,
};
setMessages((messages) => [...messages, incomingMessage]);
});
return () => {
socketRef.current.disconnect();
};
}, [roomId]);
const sendMessage = (messageBody) => {
console.log('sendMessage()');
socketRef.current.emit(NEW_CHAT_MESSAGE_EVENT, {
body: messageBody,
senderId: socketRef.current.id,
});
};
return { messages, sendMessage };
};

React component isn't updating on socket.io event

I cannot figure out why my React component is not updating once the viewer count changes. When the page first renders, the amount is displayed correctly. Socket events are logged to my terminal also just fine.
There is probably an easy fix to this. What am I doing wrong?
Server
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const port = process.env.PORT || 4001;
const index = require('./index');
const app = express();
app.use(index);
const server = http.createServer(app);
const io = socketIo(server);
io.on('connection', (socket) => {
console.log('+ client connected');
getApiAndEmit(socket);
socket.on('disconnect', () => {
console.log('- Client disconnected');
getApiAndEmit(socket);
});
});
const getApiAndEmit = (socket) => {
socket.emit('event', io.engine.clientsCount);
};
server.listen(port, () => console.log(`Listening on port ${port}`));
React
import React from 'react';
import socketIOClient from 'socket.io-client';
class App extends React.Component {
constructor() {
super();
this.state = {
response: false,
endpoint: 'http://localhost:4001',
};
}
componentDidMount() {
const { endpoint } = this.state;
const socket = socketIOClient(endpoint);
socket.on('event', (data) => this.setState({ response: data }));
}
render() {
const { response } = this.state;
return (
<p>{response ? <p>Active Users {response}</p> : <p>Loading...</p>}</p>
);
}
}
export default App;
I think the problem is that you're using the wrong type of emit. Take a look at this cheat sheet: https://socket.io/docs/emit-cheatsheet/
If you use socket.emit(), socketio only sends the event to the single, connected client, if you use socket.broadcast.emit(), it emits the event to every client except the sender, and if you use io.emit(), it emits the event to every client.
So I think your code should look something like:
io.on('connection', (socket) => {
io.emit('event', io.engine.clientsCount);
socket.on('disconnect', () => {
socket.broadcast.emit('event', io.engine.clientsCount);
});
});
Try this:
componentDidMount() {
const { endpoint } = this.state;
const socket = socketIOClient(endpoint);
let self = this;
socket.on('event', (data) => self.setState({ response: data }));
}

Resources