Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React server-side rendering without polling for changes

I'm in the process of experimenting with transitioning an existing web app from knockout to react js.

As it stands the application establishes a websocket connection to the server and receives update asynchronously (there can be many clients which can affect each others state, think chat room for example).

My Question is, if I were do the rendering server side, how could changes be pushed down to each client? I've only just started reading up on rendering on the server so I may be misunderstanding how it works but the way I believe:

Client performs an action which is sent to the server, server responds with an html fragment which the client then replaces into it's DOM

In the case of an app where the state can be changed by either the server or another client, would I still be forced to use websockets/http polling to show these updates?

Is it possible for the server to push down new fragments otherwise?

like image 952
ioseph Avatar asked Nov 13 '14 01:11

ioseph


1 Answers

With React, unidirectional flows are often the best way to do it. To achieve this, we should use an event emitter.

Your get JSON from the server using websockets, SSE, or polling (it doesn't matter). They should be in an envelope format. This would be an example for a chat application.

{
  "type": "new-message", 
  "payload": {
    "from": "someone",
    "to": "#some-channel",
    "time": 1415844019196
  }
}

When you get this message from the server, you emit it as an event.

var handleMessage = function(envelope){
   myEventEmitter.emit(envelope.type, envelope.payload);
};

This is a form of dispatcher. It simply gets the event, and broadcasts it to anyone who's interested. Usually the interested party will be a component or a store (in flux).

var MessageList = React.createClass({
   componentDidMount: function(){
      myEventEmitter.on('new-message', this.handleNewMessage);
   },
   handleNewMessage: function(message){
      if (message.to === this.props.channel) {
          this.setState({messages: this.state.messages.concat(message)});
      }
   },
   componentWillUnmount: function(){
      myEventEmitter.removeListener(this.handleNewMessage);
   },
   ...
});

When the user submits a message, you'd emit a 'user-new-message' event. The same part of code that implements handleMessage would be listening to this event, send the message to the server, and emit a new-message event so that the UI could be updated.

You can also keep a list of received messages elsewhere in your code (not in a component), or make a request to get recent messages from the server.

Sending html from the server is usually a very bad, inflexible, and unperformant idea. AJAX is for getting data to the client, and the client chooses how to present this data to the user.

like image 186
Brigand Avatar answered Sep 22 '22 15:09

Brigand