jamierossiter
jamierossiter

Reputation: 47

Socket.io - Client listens to data changes from server automatically

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

Answers (1)

Mobeen
Mobeen

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

Related Questions