K20GH K20GH - 2 months ago 34
React JSX Question

React + Sails + Socket.io

This is quite a broad question, however I currently have a Sails API server and a React Front-end (Standalone).

Note: The React Front-End is NOT part of Sails

I'm trying to get to grips with sockets, so I figured I would start simple. I want to achieve the following:


  • User visits my website (React)

  • React opens a socket and connects to Sails

  • Sails streams the data from within a function/model

  • React updates when new data is added to the model



I semi understand how this works using Express and React, however I cannot get my head around how Sails implements their version of WebSockets on top of Sockets.io.

What I've done is install the sockets.io-client within React, and then trying to use sails.sockets inside Sails.

This is what I currently have:

React Component NB: I don't think this is correct at all

componentDidMount =()=> {
this.getSessionData();
UserStore.listen(this.getSessionData);
Socket.emit('/listSessions', function(data){
console.log(data);
})
}


Sails Function (listSessions)

listSessions: function(req, res) {
Session.find({ where: {visible: true}, sort: 'createdAt DESC'},
function(err, sessions){

if(req.isSocket){
Session.watch(req.socket);
console.log('User subscribed to ' + req.socket.id);
}

if(err) return res.json(500, {
error: err,
message: 'Something went wrong when finding trades'
});

return res.json(200, {
sessions: sessions,
});
})
},


Sails Function (createSession) Trying to use publishCreate to use in conjunction with Session.watch in the above function

createSession: function(req, res){

var token = jwt.sign({
expiresIn: 30,
}, 'overwatch');


Session.create({
username: req.body.username,
platform: req.body.platform,
lookingFor: req.body.lookingFor,
microphone: req.body.microphone,
gameMode: req.body.gameMode,
comments: req.body.comments,
avatar: null,
level: null,
hash: token,
competitiveRank: null,
region: req.body.region,
visible: true,
}).exec(function(err, created){

Session.publishCreate(created);

if(err) {
console.log(err);
return res.send({
error: err,
message: 'Something went wrong when adding a session',
code: 91
})
}
if(req.isSocket){
Session.watch(req.socket);
console.log('User subscribed to ' + req.socket.id);
}
return res.send({
session: created,
code: 00,
})
});
},


Both of the Sails functions are called using POST/GET.
I'm completely stumped as where to go with this, and it seems to documentation or explanation on how to get this working is limited. All the Sails documentation on Sockets seems to relate to using Sails as a front-end and server

Answer

OK so I managed to solve this:

Simply put:

Within React, I had to include https://github.com/balderdashy/sails.io.js/tree/master

Then within my React component I did:

  componentDidMount =()=> {
    io.socket.get('/listSessions',(resData, jwres) => {
      console.log('test');
      this.setState({
        sessions: resData.sessions,
        loaded: true,
      })
    })

    io.socket.on('session', (event) => {
      if(event.verb == 'created') {

        let sessions = this.state.sessions;
        sessions.push(event.data);
        this.setState({
          sessions: sessions
        })
      } else {
        console.log('nah');
      }
    });
  }

This makes a virtual get request to Sails using Socket.io, and sets the response in state. It also watches for updates to the 'session' connection and updates the state with these updates meaning I can update a list in real time

Within my Sails controller I have:

listSessions: function(req, res) {

    if(req.isSocket){
        Session.find({ where: {visible: true},  sort: 'createdAt DESC'},
        function(err, sessions){

            Session.watch(req.socket);

            if(err) return res.json(500, {
                error: err,
                message: 'Something went wrong when finding trades'
            });

            return res.json(200, {
                sessions: sessions,
            });
        })
    }
},

The Session.watch line listens for updates via publishCreate on the model which is found in my model as follows:

  afterCreate: function(message, next) {
    Session.publishCreate(message);
     next();
   },
Comments