Not able to connect to socket.io in react native - node.js

I am trying to establish socket.io connection between nodejs and react-native. But unfortunately it is not working.
The issue is that client side do not get connected with server via sockets.
Here is nodejs (server-side) code
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);
server.listen(process.env.PORT || 8000, () => console.log('server is running on port 8000'));
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
io.on('connection', socket => {
console.log('connection')})
Here is react-native(client-side) code (trimmed)
import React from 'react'
import { Button } from 'react-native'
import io from 'socket.io-client';
const Room = props => {
const sock = useRef();
useEffect(() => {
sock.current = io.connect(<HOSTNAME>, {
forceNode: true,
transports: ['websocket'],
});
//to check if mobile connected to server
console.log('test');
console.log('check 11', sock.current.connected);
sock.current.on('connect', function() {
console.log('check 2', sock.current.connected);
});
});
}
When I try to connect I am not getting 'check 2' message in my console, which is to be printed on execution of sock.current.on('connect'....
Libraries used: react-native version:0.62.1, socket.io-client version:2.3.0 (client-side), socket.io version:2.3.0 (server-side)

Related

React/Socket.io client not connecting to server when deployed to Heroku

I'm following this tutorial: https://www.youtube.com/watch?v=tBr-PybP_9c
Locally, the app works fine - I can open up some windows and have them talk to each other. However, when I try to deploy the app to Heroku, the clients no longer connect to the server.
Server-side:
const express = require('express');
const cors = require('cors');
const socket = require('socket.io');
const dotenv = require('dotenv');
dotenv.config({ path: './config.env' });
const app = express();
app.use(cors());
const port = process.env.PORT || 8080;
const server = app.listen(port, () => {
console.log(`App running on port ${port}`);
});
const http = require('http').Server(app);
const io = socket(http, {
pingInterval: 100,
pingTimeout: 500,
cors: {
origin: '*',
},
});
io.listen(server);
io.on('connection', (socket) => {
const id = socket.handshake.query.id;
socket.join(id);
console.log(`A user has connected with ID ${id}`);
});
I deployed the server to a Heroku dyne, and it built successfully. The client is a separate dyne:
import React, { useContext, useEffect, useState } from 'react';
import io from 'socket.io-client';
const SocketContext = React.createContext();
export function useSocket() {
return useContext(SocketContext);
}
export function SocketProvider({ id, children }) {
const [socket, setSocket] = useState();
useEffect(() => {
// const newSocket = io('https://my-heroku-app.herokuapp.com:48600', {
const newSocket = io('http://localhost:8080', {
query: { id },
});
setSocket(newSocket);
return () => newSocket.close();
}, [id]);
return (
<SocketContext.Provider value={socket}>{children}</SocketContext.Provider>
);
}
This also built successfully. Obviously, localhost:8080 doesn't work when deployed to Heroku - I tried using 'https://my-heroku-app.herokuapp.com:48600' (the server application's name plus the port where it's running on Heroku), and that doesn't work either. The console.log never occurs on the server side when I do heroku logs --tail.
Is there a better way to do this? Can I put these into the same app, so I only have to deploy one project?

Translating server code to ES6 using socket.io

We are complete newbies to socket.io and express. And we have followed along this tutorial to learn socket.io https://www.valentinog.com/blog/socket-react/
And now we want to translate this line of code (older style):
const index = require("./routes/index").default
to ES6, below:
import router from './routes/index'
app.use('/', router)
But it does not work for us. We get this error in the terminal.
Full server.js code here
import express from 'express'
const app = express()
import { createServer } from 'http'
const server = createServer(app)
import { Server } from "socket.io"
const io = new Server(server)
import cors from 'cors'
import router from './routes/index'
const port = process.env.PORT || 4001
app.use('/', router)
app.use(index)
app.use(cors())
app.use(express.json())
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 disconnected")
clearInterval(interval)
})
})
const getApiAndEmit = socket => {
const response = new Date()
socket.emit("FromAPI", response)
}
app.listen(port, () => {
// eslint-disable-next-line
console.log(`Server running on http://localhost:${port}`)
})
I was able to use socket.io on my project like so:
const app = express()
const http = require('http').createServer(app)
const socketIo = require('socket.io')(http)
In other words I used require and did not use router. This might work for you unless there is a specific reason you need to do otherwise.

socket.io problems. Not able to connect. front end says connection: false and backend doesn't log anything

i am new to socket.io and i can't get it to connect to react app. here is my app.js in node
const express = require('express');
const port = process.env.PORT || 4000;
const router = require('./routes/routes');
const cors = require('cors');
const app = express();
const bodyParser = require('body-parser');
const db = require('./db/db');
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', () => {
console.log('connected');
});
app.use('*', cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
(router);
app.listen(port, () => {
console.log('listening on port ' + port);
db.sync({
// force: true,
logging: false,
});
});
and my front end code.
import React, { useState, useEffect, useRef } from 'react';
import { io } from 'socket.io-client';
import classes from './Chatroom.module.css';
const Chatroom = ({ user, getAllMessages, setGetAllMessages }) => {
const ENDPOINT = 'http://localhost:4000/getallmessages';
var socket = io(ENDPOINT);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
socket.on('connect', () => {
socket.send('hello');
console.log('connected.');
});
console.log(socket);
}, []);
Whenever i look in the console on it shows connected: false and nothing is logging on the backend.
In order to fix the issue i had to add options to my io declaration as follows.
const server = require('http').createServer(app);
const options = {
cors: true,
origins: ['http://127.0.0.1:3000'],
};
const io = require('socket.io')(server, options);
127.0.0.1 being home and on client side my server is on 3000 so that's where that comes from. and on the client side you were right i had to remove "getallmessages" route so now it is as follows.
onst ENDPOINT = 'http://localhost:4000/';
var socket = io(ENDPOINT);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
socket.on('connect', () => {
socket.send('hello');
console.log('connected.');
});
console.log(socket);
}, []);
socket.io is bound to the server object so you should listen to the server instead of the app.
Change app.listen to server.listen
Change endpoint by removing getallmessages if you are not using namespaces

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

Cannot establish connection between server and client using socket.io with NodeJS, ReactJS and Express

I have read blogs and seen videos where this results in successful connection between the server and client, but for some reason it doesn't seem to work on my system.
This is the code on the server side:
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const PORT = 3001;
io.on('connection', socket => {
console.log('a user connected.');
});
http.listen(PORT, () => {
console.log('listening on port ' + PORT);
});
And this is the code on the client side:
import React, { useEffect } from 'react';
import io from 'socket.io-client';
const socket = io('http://127.0.0.1:3001');
function Test() {
return (
<div>
Test
</div>
)
}
export default Test;
I have checked the versions of both socket.io and socket.io-client and they are at 3.0.4
I have tried using io.connect(url) instead of just io(url)
I have tried replacing 127.0.0.1 with localhost and even 192.168.29.101. (I'm sorry, just a beginner and not sure how these things work in depth).
Thanks for all the help!
You could try to wrap the socket in useEffect() and add transports. Something like that:
import React, { useState, useEffect } from "react";
import openSocket from "socket.io-client";
function App() {
const [response, setResponse] = useState("");
useEffect(() => {
const socket = openSocket("http://localhost:3001", {
transports: ["websocket"],
});
socket.on("message", data => {
setResponse(data);
});
}, []);
return (
<p>
{response}
</p>
);
}
export default App;
In your server you need to specify the event to emit:
const express = require("express");
const app = express();
const server = app.listen(3001, () => {
console.log("listening on port 3001");
});
const io = require("socket.io")(server);
io.on("connection", (socket) => {
console.log("Client connected");
socket.emit("message", "Hello Socket!");
});

Resources