I want to build a ReactJS/NodeJs app with Socket IO.
I am able to establish a socket connection between the client and the server, but whenever I press the button to emit a message, nothing happens on the server side, meaning the console.log('new message:', msg)is not triggered.
Client code:
import React from 'react';
import io from 'socket.io-client';
const socket = io.connect('http://localhost:4000');
function App() {
socket.on('message', msg => {
console.log('new message:', msg);
});
const handleMessageSend = () => {
socket.emit('message', 'test');
}
return (
<button onClick={handleMessageSend}>Send</button>
);
}
export default App;
Server:
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
io.on('connection', socket => {
socket.on('message', msg => {
console.log('new message:', msg);
socket.emit('message', msg)
})
})
http.listen(4000, () => {
console.log('Listening on port 4000');
})
Any ideas ? Thanks a lot in advance
I have moved socket code inside handleMessageSend.
And you can add preventDefault to prevent your page refreshing (I am not sure if you need this because you are not using a form and submit button, but you can use it for now.)
Can you please try this and let me know if it works?
React component:
import io from 'socket.io-client';
function App() {
let serverUrl = 'localhost:4000'
let socket = io(serverUrl);
const handleMessageSend = (e) => {
e.preventDefault();
socket.emit("message", "test message")
socket.on("message", function(msg){
console.log("socket working on the frontend: ", msg);
});
}
return (
<button onClick={handleMessageSend}>Send</button>
);
}
export default App;
And here server file :
const express = require ("express");
const socket = require ("socket.io");
const app = express();
const server = app.listen(4000, () => {
console.log('Listening on port 4000');
})
const io = socket(server);
io.on('connection', socket => {
socket.on('message', msg => {
console.log('socket working at the backend', msg);
io.sockets.emit('message', msg)
})
})
Related
I'm building a dummy chat app to know how socket.io works (with react and node. Everything seems to work fine except that socket io emits more than one message.
It looks like for each character I type when then I press on submit it emits the message multiplying the total of characters per 2.
How can I solve this?
Thank you!
Client
import React from "react";
import { useState } from "react";
import { io } from "socket.io-client";
const App = () => {
const socket = io("http://localhost:5000");
const [input, setInput] = useState("");
const handleChange = (e) => {
setInput(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
socket.emit("chat-message", input);
};
socket.on("chat-message", (msg) => {
console.log(msg);
});
return (
<div className="App">
<h1>Chat</h1>
<form onSubmit={handleSubmit}>
<input onChange={handleChange} type="text" id="input" />
<button type="submit">Send</button>
</form>
<div id="messages">
</div>
</div>
);
};
export default App;
Server
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server, {
cors: {
origin: '*',
}
});
io.on('connection', (socket) => {
socket.on('chat-message', (msg) => {
io.emit('chat-message', msg);
})
});
server.listen(5000, () => {
console.log('listening on: 5000');
});
Because you are getting message twice from client and the server. It goes like this
you send(emit) message from client onto "chat-message"
then your client responds to socket.on("chat-message") and prints it once
your server responds to socket.on('chat-message') and emits it back to client
client react to re emitted message from server and prints again
Can you once try this code?
//client side changes
const handleSubmit = (e) => {
e.preventDefault();
socket.emit("chat-message", input);
};
socket.on("receive-message", (msg) => {
console.log(msg);
});
//server side changes
io.on('connection', (socket) => {
socket.on('chat-message', (msg) => {
io.emit('receive-message', msg);
})
});
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!");
});
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 }));
}
I am going to make a private chat app like WhatsApp.
I connect to the server successfully
but the socket after several seconds gets disconnect from the server.
while on the client it doesn't disconnect.
Server code:
const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const port = 3000;
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
const onlineusers = {};
const socketid = {};
io.on('connection', cs => {
cs.on('online', username => {
if(username){
onlineusers[username] = cs.id;
socketid[cs.id] = username;
}
console.log("\nonline: ", onlineusers);
});
cs.on('disconnect', () => {
delete onlineusers[socketid[cs.id]];
console.log("\noffline: ", onlineusers);
});
});
const chat = io.of("/chat");
chat.on('connection', cs => {
cs.on('startchat', username => {
if (username){
chat.to('/chat#'+onlineusers[username]).emit('hey', 'I love programming');
}
});
});
server.listen(port, err => {
if(err){
console.error("Some Error: "+err);
}else{
console.log(`Server is running on port: ${port}`);
}
});
MY CLIENT code is by react-native and socket.io-client:
On line users file:
import io from 'socket.io-client';
const SocketEndpoint = 'http://192.168.43.172:3000';
this.socket = io(SocketEndpoint, {
transports: ['websocket']
});
this.socket.on('connect', () => {
if (this.state.username) {
this.socket.emit("online", this.state.username);
}
});
this.socket.on('connect_error', (err) => {
Alert.alert(err);
});
this.socket.on('disconnect', () => {
Alert.alert('disconnected');
});
Chat page file:
import io from 'socket.io-client';
const SocketEndpoint = 'http://192.168.43.172:3000/chat';
this.socket = io(SocketEndpoint, {
transports: ['websocket']
});
this.socket.on('connect', () => {
if (theirusername) {
this.socket.emit('startchat', theirusername);
}
this.socket.on('hey', data => {
alert(data);
});
this.socket.on('janajan', data => {
alert(data);
});
});
I want to keep to client socket on the server until the client themselves gets the disconnect.
because here when I want to say hey it gets a disconnect and my message could pass to the client.
thank you before
server sided code
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
io.once('connection', function (socket) {
console.log(`New connection`)
socket.emit('hello', 'hello from the server')
socket.on('clientData', (data) => {
console.log(data)
})
})
server.listen(3000, () => {
console.log(`Server started: http://localhost:${port}`)
})
Client side code:
var socket = io()
var hello = 'Hello server'
socket.on('connection', function() {
console.log('established connection')
socket.emit('clientData', hello)
})
socket.on('hello', function(data) {
console.log(data)
})
When run the client doesnt emit the 'clientData' for some reason, what am I doing wrong.
I think your socket.on("connection", use on the client is misguided. The connection event happens at the server when new clients join.
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
io.on('connection', function (socket) {
// #2 - This will run for the new connection 'socket' and set up its callbacks
// #3 - send to the new client a 'hello' message
socket.emit('hello', 'hello from the server')
socket.on('clientData', (data) => {
// #6 - handle this clients 'clientData'
console.log(data)
})
})
server.listen(3000, () => {
console.log("Server started: http://localhost:${port}")
})
Client side code:
// #1 - this will connect to the server and send the 'connection'
var socket = io()
var hello = 'Hello server'
socket.on('hello', function(data) {
// #4 - 'hello' response after connecting
console.log(data)
// #5 - send 'clientData'
socket.emit('clientData', hello)
})