Reputation: 47
I'm trying to make something similar to a multiplayer game lobby using ReactJS, NodeJS and Socket.IO. Each time a new player/client connects to the socket, I want their name to be broadcasted on the frontend.
So far I've been able to achieve this by having the frontend make a GET request to the backend every 3 seconds, which triggers a socket on the backend to send data obtained from a mongoDB database.
FRONTEND - lobby.js
class Lobby extends Component {
//When the component mounts, it calls grabNames function every 3 seconds.
componentDidMount = () => {
setInterval(this.grabNames, 3000);
};
//function makes a GET request that triggers the socket to emit a "joinedPlayers" message.
grabNames = () => {
axios.get(`${backend}/playerNames`).then(response => {
console.log("Success");
});
//Listens for the "joinedPlayers" message to be emitted from the backend.
//The joinedPlayers state is then referenced in the client-side markup.
socket.on("joinedPlayers", data => {
this.setState({ joinedPlayers: data.map(name => <li>{name}</li>) });
});
};
BACKEND - server.js
//Function for connecting to the mongoDB database through Mongoose.
function dbConnect() {
mongoose
.connect(database, { useNewUrlParser: true })
.catch(error => console.error(error));
}
//Socket Connection
io.on("connection", socket => {
console.log("A connection to the socket has been established.");
});
//Router
app.get("/playerNames", (req, res) => {
dbConnect();
Name.find((error, array) => {
var playerNames = array.map(name => name.name);
io.emit("joinedPlayers", playerNames);
res.send("Player names emitted.");
});
});
Whilst this method is working for me, I can't help but think there is a better way for the frontend to listen for changes to the data from the server.
For instance, is there a way the server can detect a change in my mongoDB database and update the client only when it detects this change... rather than having to periodically check every 3 seconds regardless of whether there is a change to the data or not?
Any help would be greatly appreciated. Thank you!
Upvotes: 0
Views: 2749
Reputation: 985
Instead of making a GET request, It's preferable that you create room/channel for each game and connect all players to that room (from client-side). Now when the new player will subscribe to that room, (An event will trigger). You can have an event broadcasted for the channel.
Something like below:
io.on('connection', function(socket){
socket.on('joinedPlayers', function(id, msg){
socket.broadcast.to('game id').emit('Jamie joined', msg);
});
});
Check this out for more on this: https://socket.io/docs/rooms-and-namespaces/#Default-room
Upvotes: 1