When emit a event to the websocket server, the server receive the event once and send a response, but the client receive the event multiple time:
result expected
result received
client side:
client.emit("test", {
room: props.room,
});
client.on("testResponse", () => {
console.log("test response app");
});
server side :
socket.on("test", (data: { room: string }) => {
console.log("test");
io.in(data.room).emit("testResponse", {});
});
UPDATE:
on the client side I got to put the socket.on('response,()=>{...}) in the UseEffect of the component and add a socket.off in the return of the useEffect
useEffect(() => {
socket.on("testResponse", () => {
console.log("test response app");
});
return () => {
socket.off("testResponse");
};
});
Related
I am trying to send some data (number) from client to server via socket.emit. The problem is that server doesn't seem to receive any data because only null is consoled out or I am trying to get it wrong. Where might be a problem?
client side
useEffect(() => {
getMessages();
socket.emit("openedConversation", { conversationId });
}, []);
server side
io.on("openedConversation", ({ conversationId }) => {
console.log(conversationId);
});
};
check this code
io.on("openedConversation", conversationId => {
console.log(conversationId);
});
The socket have to listen to the server when i send a new message.
The messages arrive because when i refresh the page i can see them.
Server side socket i know is working find because in other frontend app the same client socket is working find.
This socket is called every time the user select a new chat in the web.
Here is the socket service in my app:
import openSocket from "socket.io-client";
function connectToSocket() {
return openSocket("http://localhost:8080");
}
export default connectToSocket;
And here is the code executed when user select a chat:
// how i am importing the socket
import openSocket from "../../Services/socket-io"
async function fetchMessages(ticketId) {
try {
const { data } = await api.get("/messages/" + ticketId, {
params: { pageNumber },
});
if (ticketId === data.ticket.id) {
await loadMessages(data, ticketId);
}
listenMessages(ticketId);
} catch (err) {
Toast.ToastError("Error trying to load messages");
}
};
function listenMessages(ticketId) {
const socket = openSocket();
socket.on("connect", () => socket.emit("joinChatBox", ticketId));
socket.on("appMessage", (data) => {
if (data.action === "create") {
console.log(data);
}
if (data.action === "update") {
console.log(data);
}
});
}
What i already tried:
Use the same socket version both in client and server (3.0.5).
Calling listenMessages every time a message is sent.
socket.io-client version 4.
I have this code in my service worker:
messaging.onBackgroundMessage(function (payload) {
console.log("onBackgroundMessage email and contact_link:");
console.log(payload.data.email,payload.data.contact_link);
self.clients.matchAll().then(clients => {
clients.forEach(client => client.postMessage({
msg: "This is a message from the SW",
email: payload.data.email,
contact_link: payload.data.contact_link
}));
})
});
I have this code on the client:
navigator.serviceWorker.addEventListener('message', payload => {
console.log("Message from ServiceWorker");
console.log(payload.data.msg, payload.data.email, payload.data.contact_link);
});
I get the data properly on the console from the service worker, however the client's console says all the data is undefined.
Why is that, what am I doing wrong?
I still do not know why it does not work, but I used this code on the server:
const channel = new BroadcastChannel('sw-messages');
channel.postMessage(payload.data);
And this code on the client instead:
const channel = new BroadcastChannel('sw-messages');
channel.addEventListener('message', event => {
console.log('Received:', event.data);
});
It works well.
I'm having a problem with socket.io at the moment I try to send a second time from the server to the client
here is the server code with express and socket.io
io.on('connection', async function (socket) {
let socketId = socket.id;
const mta = new Client("20.64.24.144", 22005, "*", "*");
mta.resources.evokestats.getPlayerCount()
.then((result) => {
console.log("result", result);
socket.emit("players-start", { players: result })
})
.catch((err) => {
console.error(`Ooops! Something went wrong ${err}`);
});
app.post('/player_connect', async function (req, res) {
let ip = req.body[0];
let player = await players.findOne({ ip: ip })
if (player) {
await socket.emit("players", { players: req.body[1] })
} else {
try {
player = await players.create({ ip: ip, name: req.body[2] })
await socket.emit("players", { players: req.body[1] })
await socket.emit("last_24_players", { players: 1 });
} catch (error) {
console.log("error", error)
}
}
res.send("connected")
});
});
and here is my client with reactjs and socket.io
useEffect(() => {
getStats();
}, [])
async function getStats(params) {
socket.on("players-start", function (data) {
setNowPlayers(data.players)
});
socket.on("players", function (data) {
console.log("players", data)
setNowPlayers(data.players)
});});
And in my client using react, in useEffect I listen to the "players-start" and the "players" that was emit.
players-start: It is for every first time that I enter my client he only calls once, to bring all players connected
players: Every time someone connects to the game server, a post call is made to my server where I use the express with socket, in the url '/player_connect' and then immediately emit
The problem: whenever I issue an issue on 'players-start' and then immediately enter the game server that calls the url '/player_connect' it is not triggering the issue of 'players' or at least the client is not receiving.
Test I've done:
My first attempt was to stick everything to the listener "players" but it still doesn’t work
I really appreciate everyone's help.
I'm working on SocketIO with ReactJS vie a chat app.
When emitting message to my server my client doesn't receive the response of my server. The console.log controlling the mechanism is never displayed.
I can't figure out why since I follow exactly the SocketIO blueprint.
here my client.js :
send= (e) => {
e.preventDefault();
const socket= io.connect(this.state.endpoint);
socket.emit("message", () => {
message: "hey !"
})
console.log("send ended")
}
componentDidMount(){
const socket= io.connect(this.state.endpoint);
socket.on("new_message", (message) => {
console.log("new message ", message)
})
socket.on("user_connected", (message) => {
console.log(message)
})
}
here my server.js :
client.on("message", (message) => {
client.emit("new_message", message)
})
Any hint would be great,
Thanks
The reason for your problem is that you essentially have multiple instances of socket connections created over the life span of your client component.
From the server's perspective, the "new_message" is being emitted to the socket that you created in your components send arrow function. Because that socket instance does not listen to "new_message", you're therefore not going to see the expected log messages in the console.
Perhaps you could consider refactoring your client component code like this, to connect a single socket, and use that as a single means of sending and listening to messages from the server?
class YourComponent extends Component {
// Add socket field to component class
socket : ''
// Note that the send method is not an arrow function here, so
// care should be taken to consider how you invoke send() if
// your current implementation relies on this being an arrow function
function send(e) {
e.preventDefault();
const socket = this.state.socket // UPDATE: Access socket via state
// Send messages to server via the same socket instance of this class
if(socket) {
socket.emit("message", () => {
message: "hey !"
})
console.log("send ended")
}
}
function componentDidMount(){
const socket = io.connect(this.state.endpoint)
socket.on("new_message", (message) => {
console.log("new message ", message)
})
socket.on("user_connected", (message) => {
console.log(message)
})
// UPDATE: Connect the socket, and hold a reference for reuse by the component class
// instance via the component's state (seeing you can't add a class field for this)
this.setState({ socket : socket })
}
}