Dr Mouse
Dr Mouse

Reputation: 331

Update ReactJS app using websocket

I am trying to do a supervision page for my customer, but I am struggling with updating a ReactJS app in real time. This supervision page can contains up to sixteen video flux, which can or cannot be in service at the same time.

When I generate my page with Django, I build an initial list stored in a JS variable :

var anims = {{list|safe}}

My ReactJS code for a single video flux is the following :

var ModelFlux = React.createClass({
    displayName : "Flux player",
    propTypes: {
        animID: React.PropTypes.number.isRequired,
    },
    componentDidMount:function() {
       //generating the player
    },
    render: function() {
        var newDivId = 'iv' + this.props.animID;
        return(
            React.createElement('div',{className:'col-md-3 col-sm-6 col-xs-12'},
                React.createElement('div', {id:"content"},
                    React.createElement('div',{id:newDivId,className:'smallPl'})
                )
            )
        )
    }
})

Then, I use the following to generate X flux:

var ModelFluxwithID = anims
    .map(function(anim) {return React.createElement('div',{},React.createElement(ModelFlux,{key:anim.key,animID:anim.animID}))})

And finally, I call my app :

var App = React.createClass({
    displayName : "React App",
    render: function() {
        return(
            React.createElement('div',{className:'container'},
                React.createElement('div',{className:'row'},ModelFluxwithID)
            )
        )
    }
})

ReactDOM.render(
    React.createElement(App),
    document.getElementById('react-app')
)

It is working perfectly fine when the page is generated. But my customer doesn't want to load the page each time a flux is online/offline, so I monitor in real time the status of each flux with a websocket, which update anims :

ws = new WebSocket('xxxxxx');
ws.onmessage = function(event) {
    // Update the anims variable      
}

How can I proceed to update the app when anims is changing (creating/destroying) ?

Upvotes: 2

Views: 1069

Answers (2)

Alex Young
Alex Young

Reputation: 4039

You need to keep the anim variable as state within the App class, and map your ModelFlux instances from the state. Then when the anim state is updated, the relevant child components will be updated. For example,

var App = React.createClass({
  displayName : "React App",
  render: function() {
    return(
        React.createElement('div',{className:'container'},
            React.createElement('div',{className:'row'},{this.mapAnims(this.state.anims)})
        )
    )
  },
  getInitialState: function() {
    return {
      anims: yourAnimsVariable
    };
  },
  updateAnims: function(newAnims) {
    this.setState({
      anims: newAnims
    });
  },
  mapAnims: function() {
    return this.state.anims.map(function(anim) {
       return React.createElement('div',{},React.createElement(ModelFlux,{key:anim.key,animID:anim.animID});
    }
  },
  componentWillMount: function() {
    var ws = new WebSocket('xxxxxx');
    ws.onmessage = event => {
        this.updateAnims(event.data.anims); //or wherever your new anim data is in the event    
    }
  }
});

ReactDOM.render(
  React.createElement(App),
  document.getElementById('react-app')
)

Upvotes: 1

Dr Mouse
Dr Mouse

Reputation: 331

Based on Alex Young answer and this SO question React this.setState is not a function, I finally made it ! The final trick was to save the App reference before the ws.on message part ! So it gives :

componentWillMount: function() {
var ws = new WebSocket('xxxxxx');
var that = this; //
ws.onmessage = function(event) {
    that.updateAnims(anims);
}

Otherwise, the this corresponds to the onmessage function, not to the ReactJS App !

Upvotes: 0

Related Questions