-1

I have an application which uses react with flux and a webserver that stores all the data and notifies all the subscribers when an update has occured through a websocket.

My problem is that when my component triggers an action the new state is sent to the webserver through the socket and to the store at the clients browser, but then my server will send a message to all subscribers that this is the new state for this component so that all clients gets updated but this causes the client to send a new update that the state has changed. And this goes in a infinite loop where client send to server and server responds with the update to all subscribers and since it is an update the client sends the new state to the server again...

utils/WebAPI:

var socket = new SockJS("http://localhost:8080/stomp");
var client = Stomp.over(socket);

module.exports = {

    sendUpdate: function(update){
        if(client.connected){
            client.send("/app/hello", {}, JSON.stringify(update));
        }
    },

    getUpdates: function() {
        client.connect({}, function() {
            client.subscribe("/topic/hello", function(message) {
                var data = JSON.parse(message.body);
                MyActions.updateState(data.id, data.update)
            });
        });
    }

};

MyActions:

var AppDispatcher = require('../dispatcher/AppDispatcher');
var FunctionConstants = require('../constants/FunctionConstants');

// Define actions object
var MyActions = {

    updateState: function(id, update) {
        AppDispatcher.handleAction({
            actionType: FunctionConstants.STATE_UPDATED,
            id: id,
            update: update
        })

    }

};

module.exports = MyActions;

The update function in my store:

var WebAPI = require('../utils/WebAPI');
var _ = require('underscore');

// Define initial data points
var _data = {};


function updateFunction(id, data) {

    _data[id] = data

    var update = "{\"actionType\": \"STATE_UPDATED\", \"id\": \""+id+"\", \"update\": "+JSON.stringify(data)+"}";
    WebAPI.sendUpdate(JSON.parse(update));
}

...

And finally my component:

let React = require('react');
var MyActions = require('../../../actions/MyActions');
var WebAPI = require('../../../utils/WebAPI');

//Subscribe for updates sent from server
WebAPI.getUpdates();

let FunctionComponent = React.createClass({

    newState: function(data){
        MyActions.updateState(this.props.id, data);
    },

    render() {
        var d = this.props.data;
        d.count++;
        return ( 
            <div>
                <h1>{this.props.id}</h1>
                <div>{this.props.data}</div>
                <button onClick={this.newState(d)}
            </div>
        )
    }
});

module.exports = FunctionComponent;

How can I overcome this problem that causes an infinite loop when my component calls any action and the server sends an update to all subscribers?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
vato
  • 409
  • 1
  • 3
  • 15

1 Answers1

0

WebAPI.getUpdates(); should be in the store, not the component. Following is a basic store using reflux. See this for the rest; Flux: waitFor specific event.

    import Reflux from 'reflux';

    import Actions from './Actions';
    import AddonStore from './Addon.Store';
    import MixinStoreObject from './Mixin.Store';

    let BasicStoreObject = {
        init() { this.listenTo(AddonStore, this.onAddonTrigger); },
        data1: {},
        listenables: Actions,
        mixins: [MixinStoreObject],
        onGotData1(data) { this.data1 = data; BasicStore.trigger('data1'); },
        onAddonTrigger() { BasicStore.trigger('data2'); },
        getData1() { return this.data1; },
        getData2() { return AddonStore.data2; },
        getData3() { return this.data3; }
    }
    const BasicStore = Reflux.createStore(BasicStoreObject);
    export default BasicStore;
Community
  • 1
  • 1
J. Mark Stevens
  • 4,911
  • 2
  • 13
  • 18
  • Well actually it does not matter where I put it since it will just open up a socket and listen when data comes from the server and then call MyAction. It is only important that this socket is initialized somewhere in my app – vato Oct 06 '15 at 15:31
  • That may be so, but it is the only piece of code showing that could account for your loop problem. If the update action is only called by the button click event it will not be triggered by a prop update. It is easier to debug if you only have one place in your code that interacts with your webapi. – J. Mark Stevens Oct 06 '15 at 17:18
  • Loop is caused in getUpdates in my webapi because when an updated is received from server a call will travel to my store which will again send an update to the server. Is there some possible way with flux architecture to check in my store updateFunction() if the update comes from the server or from the view, because if the update comes from the server then I don't need to call the WebAPI to notify the server of the update in my updateFunction(). – vato Oct 06 '15 at 17:31
  • I didn't look closely enough. You need a separate action for updates from the server and updates from the component. Updates from the server should be handled by the store and then passed to the component. Updates from the component should also be handled by the store and then passed to the server. An partial example is here; http://stackoverflow.com/questions/32537568/flux-waitfor-specific-event/32542242#32542242. I will add the basic.store above. – J. Mark Stevens Oct 06 '15 at 20:30
  • Thanks, I believe I got it now. – vato Oct 06 '15 at 22:03